Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
thread_bootstrap.c
00001 /* 00002 * Copyright (c) 2014-2018, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 /* 00031 * \file thread_bootstrap.c 00032 * \brief Add short description about this file!!! 00033 * 00034 */ 00035 #include "nsconfig.h" 00036 #ifdef HAVE_THREAD 00037 #include <string.h> 00038 #include <ns_types.h> 00039 #include <nsdynmemLIB.h> 00040 #include "eventOS_event.h" 00041 #include "eventOS_event_timer.h" 00042 #include "randLIB.h" 00043 #include "ns_sha256.h" 00044 #include "common_functions.h" 00045 #include "NWK_INTERFACE/Include/protocol.h" 00046 #include "net_thread_test.h" 00047 #include "ipv6_stack/protocol_ipv6.h" 00048 #include "libDHCPv6/libDHCPv6.h" 00049 #include "libDHCPv6/libDHCPv6_server.h" 00050 #include "ns_trace.h" 00051 #include "coap_service_api.h" 00052 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00053 #include "6LoWPAN/Thread/thread_common.h" 00054 #include "6LoWPAN/Thread/thread_routing.h" 00055 #include "6LoWPAN/Thread/thread_nd.h" 00056 #include "6LoWPAN/Thread/thread_bootstrap.h" 00057 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00058 #include "6LoWPAN/Thread/thread_discovery.h" 00059 #include "6LoWPAN/Thread/thread_leader_service.h" 00060 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00061 #include "6LoWPAN/Thread/thread_management_internal.h" 00062 #include "6LoWPAN/Thread/thread_management_server.h" 00063 #include "6LoWPAN/Thread/thread_neighbor_class.h" 00064 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00065 #include "6LoWPAN/Thread/thread_network_synch.h" 00066 #include "6LoWPAN/Thread/thread_joiner_application.h" 00067 #include "6LoWPAN/Thread/thread_bbr_commercial.h" 00068 #include "6LoWPAN/Thread/thread_management_client.h" 00069 #include "6LoWPAN/Thread/thread_joiner_application.h" 00070 #include "6LoWPAN/Thread/thread_bbr_api_internal.h" 00071 #include "6LoWPAN/Thread/thread_border_router_api_internal.h" 00072 #include "6LoWPAN/Thread/thread_beacon.h" 00073 #include "6LoWPAN/Thread/thread_nvm_store.h" 00074 #include "6LoWPAN/Thread/thread_ccm.h" 00075 #include "6LoWPAN/MAC/mac_helper.h" 00076 #include "6LoWPAN/Thread/thread_mle_message_handler.h" 00077 #include "mac_api.h" 00078 #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up 00079 #include "thread_management_if.h" 00080 #include "thread_border_router_api.h" 00081 #include "thread_tmfcop_lib.h" 00082 #include "Common_Protocols/ipv6.h" 00083 #include "Common_Protocols/icmpv6.h" 00084 #include "Common_Protocols/icmpv6_radv.h" 00085 #include "MPL/mpl.h" 00086 #include "MLE/mle.h" 00087 #include "MLE/mle_tlv.h" 00088 #include "DHCPv6_client/dhcpv6_client_api.h" 00089 #include "thread_config.h" 00090 #include "thread_meshcop_lib.h" 00091 #include "multicast_api.h" 00092 #include "mlme.h" 00093 #include "Service_Libs/etx/etx.h" 00094 #include "Service_Libs/nd_proxy/nd_proxy.h" 00095 #include "Service_Libs/blacklist/blacklist.h" 00096 #include "Service_Libs/mle_service/mle_service_api.h" 00097 #include "6LoWPAN/MAC/mac_data_poll.h" 00098 #include "6LoWPAN/lowpan_adaptation_interface.h" 00099 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00100 #include "platform/topo_trace.h" 00101 00102 #define TRACE_GROUP "thbs" 00103 00104 //#define EXTRA_DEBUG_INFO 00105 #ifdef EXTRA_DEBUG_INFO 00106 #define tr_debug_extra(...) tr_debug(__VA_ARGS__) 00107 #else 00108 #define tr_debug_extra(...) 00109 #endif 00110 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur); 00111 00112 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur_interface); 00113 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration); 00114 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur); 00115 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur); 00116 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state); 00117 static void thread_bootsrap_network_discovery_failure(int8_t interface_id); 00118 00119 static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data); 00120 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info); 00121 00122 #ifdef HAVE_THREAD_V2 00123 00124 static bool enabled = false; 00125 static uint32_t addr_notificastion_timer; 00126 static uint32_t mlr_timer; 00127 00128 static void thread_bootstrap_pbbr_network_data_process(struct protocol_interface_info_entry *cur); 00129 static void thread_bootstrap_pbbr_update_done(struct protocol_interface_info_entry *cur); 00130 00131 #else 00132 #define thread_bootstrap_pbbr_network_data_process(cur) 00133 #define thread_bootstrap_pbbr_update_done(cur) 00134 00135 #endif 00136 00137 static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data) 00138 { 00139 protocol_interface_info_entry_t *cur = user_data; 00140 lowpan_adaptation_remove_free_indirect_table(cur, entry_ptr); 00141 00142 thread_reset_neighbour_info(cur, entry_ptr); 00143 //Removes ETX neighbor 00144 etx_neighbor_remove(cur->id, entry_ptr->index ); 00145 //Remove MLE frame counter info 00146 mle_service_frame_counter_entry_delete(cur->id, entry_ptr->index ); 00147 } 00148 00149 static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) 00150 { 00151 protocol_interface_info_entry_t *cur_interface = user_data; 00152 00153 if (thread_am_router(cur_interface)) { 00154 return false; //Never do Keep alive with any one 00155 } 00156 00157 if (entry_ptr->link_role != PRIORITY_PARENT_NEIGHBOUR) { 00158 return false; //Do not never challenge than priority parent 00159 } 00160 00161 if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { 00162 return false; //Sleepy end device should not never challenge 00163 } 00164 00165 if (entry_ptr->lifetime > MLE_TABLE_CHALLENGE_TIMER) { 00166 return false; 00167 } 00168 00169 return thread_host_bootstrap_child_update(cur_interface, entry_ptr->mac64 ); 00170 } 00171 00172 int8_t thread_mle_class_init(int8_t interface_id) 00173 { 00174 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00175 if (!cur) { 00176 return -1; 00177 } 00178 00179 mac_description_storage_size_t buffer; 00180 //Read MAC device table sizes 00181 if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) { 00182 return -1; 00183 } 00184 00185 if (buffer.key_description_table_size < 4) { 00186 return -1; 00187 } 00188 00189 thread_neighbor_class_delete(&cur->thread_info->neighbor_class); 00190 00191 if (!thread_neighbor_class_create(&cur->thread_info->neighbor_class, buffer.device_decription_table_size - 1)) { 00192 return -1; 00193 } 00194 00195 if (!mac_neighbor_info(cur)) { 00196 mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size - 1, thread_neighbor_remove 00197 , thread_neighbor_entry_nud_notify, cur); 00198 if (!mac_neighbor_info(cur)) { 00199 return -1; 00200 } 00201 } 00202 00203 if (mle_service_frame_counter_table_allocate(interface_id, buffer.device_decription_table_size - 1)) { 00204 return -1; 00205 } 00206 00207 if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size - 1)) { 00208 return -1; 00209 } 00210 00211 lowpan_adaptation_interface_etx_update_enable(cur->id); 00212 00213 //Defined well know neighbour for discovery 00214 00215 return 0; 00216 } 00217 00218 00219 00220 uint8_t thread_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur) 00221 { 00222 uint8_t mle_mode = 0; 00223 if (!thread_info(cur)) { 00224 return 0; 00225 } 00226 if (cur->mac_parameters->RxOnWhenIdle) { 00227 mle_mode |= MLE_RX_ON_IDLE; 00228 } 00229 00230 if (thread_info(cur)->requestFullNetworkData) { 00231 mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET); 00232 } 00233 if (thread_joiner_application_provisioning_get(cur->id) == PROVISIONING_STATUS_NOT_DONE) { 00234 // if provisioning is not done Sleepy devices need to temporarily request full network data 00235 // To receive commissioner information 00236 mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET); 00237 } 00238 00239 /* We always send secured data requests */ 00240 mle_mode |= MLE_THREAD_SECURED_DATA_REQUEST; 00241 00242 switch (thread_info(cur)->thread_device_mode) { 00243 case THREAD_DEVICE_MODE_ROUTER: 00244 case THREAD_DEVICE_MODE_FULL_END_DEVICE: 00245 mle_mode |= MLE_FFD_DEV; 00246 break; 00247 00248 default: 00249 break; 00250 } 00251 00252 00253 return mle_mode; 00254 } 00255 00256 /** 00257 * Return lower (worse) of the two margins. 00258 */ 00259 uint8_t thread_parent_margin_calc(uint8_t marginFromParent, uint8_t marginToParent) 00260 { 00261 if (marginFromParent > marginToParent) { 00262 return marginToParent; 00263 } else { 00264 return marginFromParent; 00265 } 00266 } 00267 00268 uint8_t thread_compute_link_margin(int8_t rssi) 00269 { 00270 if (rssi < -94) { 00271 return 0; 00272 } 00273 00274 return (rssi + 94); 00275 } 00276 00277 uint8_t thread_calculate_link_margin(int8_t dbm, uint8_t compLinkMarginFromParent) 00278 { 00279 uint8_t compLinkMarginToParent; 00280 uint8_t newLqi; 00281 00282 compLinkMarginToParent = thread_compute_link_margin(dbm); 00283 //Calculate New Combined LQI 00284 newLqi = thread_parent_margin_calc(compLinkMarginFromParent, compLinkMarginToParent); 00285 return newLqi; 00286 } 00287 00288 bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_temp) 00289 { 00290 if (entry_temp && thread_info(cur)->thread_endnode_parent) { 00291 if (memcmp(entry_temp->mac64 , thread_info(cur)->thread_endnode_parent->mac64, 8) == 0) { 00292 return true; 00293 } 00294 } 00295 return false; 00296 } 00297 00298 bool thread_bootstrap_request_network_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, uint16_t short_address) 00299 { 00300 bool requestNetworkdata = false; 00301 thread_leader_data_t *leaderInfo = thread_info(cur)->thread_leader_data; 00302 00303 if (thread_info(cur)->thread_endnode_parent->shortAddress != short_address) { 00304 return false; 00305 } 00306 00307 if (!thread_partition_match(cur, leaderData)) { 00308 tr_debug("Learn new Network Data"); 00309 requestNetworkdata = true; 00310 thread_partition_info_update(cur, leaderData); 00311 } else if (common_serial_number_greater_8(leaderData->dataVersion, leaderInfo->dataVersion)) { 00312 requestNetworkdata = true; 00313 00314 } else if (common_serial_number_greater_8(leaderData->stableDataVersion, leaderInfo->stableDataVersion)) { 00315 requestNetworkdata = true; 00316 00317 } 00318 00319 if (requestNetworkdata) { 00320 thread_bootstrap_parent_network_data_request(cur, true); 00321 } 00322 return true; 00323 } 00324 00325 static int thread_router_check_previous_partition_info(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv) 00326 { 00327 if (!routeTlv || !routeTlv->dataPtr || !routeTlv->tlvLen || !leaderData) { 00328 //check for parameters 00329 return -1; 00330 } 00331 if ((leaderData->partitionId == cur->thread_info->previous_partition_info.partitionId) && 00332 (leaderData->weighting == cur->thread_info->previous_partition_info.weighting) && 00333 (routeTlv->dataPtr[0] == cur->thread_info->previous_partition_info.idSequence)) { 00334 //drop the advertisement from previuos partition 00335 return 1; 00336 } else { 00337 //do not drop the advertisement 00338 return 0; 00339 } 00340 } 00341 int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uint8_t heard_partition_routers, thread_leader_data_t *heard_partition_leader_data, mle_tlv_info_t *routeTlv) 00342 { 00343 uint8_t active_routers = 0; 00344 thread_leader_data_t *current_leader_data = NULL; 00345 00346 /* if there scanned parent, then the comparison is between parent responses so retrieve the previously scanned parent info 00347 * else comparison is between existing leader data and heard advertisement leader data so retrieve existing leader data 00348 */ 00349 if (thread_info(cur)->thread_attach_scanned_parent) { 00350 current_leader_data = &thread_info(cur)->thread_attach_scanned_parent->leader_data; 00351 active_routers = thread_info(cur)->thread_attach_scanned_parent->activeRouters; 00352 } else { 00353 current_leader_data = thread_info(cur)->thread_leader_data; 00354 active_routers = thread_routing_count_active_routers(&thread_info(cur)->routing); 00355 } 00356 00357 if (!current_leader_data) { 00358 tr_warn("There is no leader data present"); 00359 return -2; 00360 } 00361 00362 if (1 == thread_router_check_previous_partition_info(cur, heard_partition_leader_data, routeTlv)) { 00363 tr_debug("Dropping advertisement from old partition without sequence number increase"); 00364 return -2; 00365 } 00366 00367 /*Rule 0: If we are going to form Higher partition than heard we dont try to attach to lower ones 00368 */ 00369 if (thread_common_ccm_enabled(cur) && 00370 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00371 if (heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) { 00372 tr_debug("Heard a lower weight partition"); 00373 return -2; 00374 } 00375 if (heard_partition_leader_data->weighting > thread_info(cur)->partition_weighting) { 00376 return 2; 00377 } 00378 } 00379 00380 if ((heard_partition_routers == 0 && active_routers == 1) && thread_am_router(cur)) { 00381 //heard a REED and I am a lonely router in a singleton partition, so merge 00382 tr_debug("Heard a REED and I am a singleton - merge"); 00383 return 2; 00384 } 00385 00386 //Rule 1: A non-singleton Thread Network Partition always has higher priority than a singleton Thread Network Partition 00387 if (heard_partition_routers > 1 && active_routers == 1) { 00388 tr_debug("Heard a nonsingleton and i am a singleton"); 00389 return 2; 00390 } 00391 if (active_routers > 1 && heard_partition_routers == 1) { 00392 return -2; 00393 } 00394 00395 /*Rule 2: When comparing two singleton or two non-singleton Thread Network Partitions, 00396 the one with the higher 8-bit weight value has higher priority. */ 00397 if (heard_partition_leader_data->weighting > current_leader_data->weighting) { 00398 tr_debug("Heard a greater weighting"); 00399 return 2; 00400 } 00401 00402 if (heard_partition_leader_data->weighting < current_leader_data->weighting) { 00403 return -2; 00404 } 00405 00406 /*Rule 3: When comparing two singleton or two non-singleton Thread Network Partitions that have the same 8-bit weight value, 00407 * the one with the higher Partition ID, considered as unsigned 32-bit numbers, has higher priority. 00408 */ 00409 if (heard_partition_leader_data->partitionId > current_leader_data->partitionId) { 00410 tr_debug("Heard a greater partition id"); 00411 return 2; 00412 } 00413 00414 if (heard_partition_leader_data->partitionId < current_leader_data->partitionId) { 00415 return -2; 00416 } 00417 00418 return -2; 00419 } 00420 00421 int thread_leader_data_validation(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv) 00422 { 00423 if (!thread_info(cur)->thread_leader_data) { 00424 return -1; 00425 } 00426 if (!thread_partition_match(cur, leaderData)) { 00427 uint8_t routers_in_route_tlv = thread_get_router_count_from_route_tlv(routeTlv); 00428 //partition checks 00429 return thread_bootstrap_partition_process(cur, routers_in_route_tlv, leaderData, routeTlv); 00430 } 00431 00432 //Should check is there new version numbers 00433 if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion) || 00434 common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) { 00435 // Version number increased by some-one else -> there is leader in the network 00436 if (thread_info(cur)->leader_private_data) { 00437 tr_error("Another leader detected -> bootstrap"); 00438 thread_bootstrap_reset_restart(cur->id); 00439 return -1; 00440 } 00441 tr_debug("NEW Network Data available"); 00442 return 1; 00443 } 00444 00445 return 0; 00446 } 00447 00448 void thread_bootstrap_all_nodes_address_generate(uint8_t multicast_address[16], uint8_t prefix[8], uint8_t scope) 00449 { 00450 memset(multicast_address, 0, 16); 00451 multicast_address[0] = 0xff; 00452 multicast_address[1] = 0x30 | scope; //Thread specification says p and t bits are 1 00453 multicast_address[2] = 0x00; //Reserved 00454 multicast_address[3] = 0x40; //Prefix length 64 bits 00455 memcpy(&multicast_address[4], prefix, 8); 00456 multicast_address[15] = 1; 00457 } 00458 00459 void thread_bootstrap_all_nodes_multicast_register(protocol_interface_info_entry_t *cur) 00460 { 00461 uint8_t multicast_address[16]; 00462 00463 switch (cur->thread_info->thread_device_mode) { 00464 #ifdef HAVE_THREAD_ROUTER 00465 case THREAD_DEVICE_MODE_ROUTER: 00466 cur->if_special_multicast_forwarding = thread_router_bootstrap_multicast_forwarder_enable; 00467 break; 00468 #endif 00469 00470 default: 00471 cur->if_special_multicast_forwarding = NULL; 00472 break; 00473 } 00474 00475 // Register to link local all thread nodes multicast 00476 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); 00477 tr_debug("Register multicast address: %s", trace_ipv6(multicast_address)); 00478 addr_add_group(cur, multicast_address); 00479 00480 // Register to mesh local all thread nodes multicast 00481 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); 00482 tr_debug("Register multicast address: %s", trace_ipv6(multicast_address)); 00483 addr_add_group(cur, multicast_address); 00484 } 00485 00486 void thread_bootstrap_all_nodes_multicast_unregister(protocol_interface_info_entry_t *cur) 00487 { 00488 uint8_t multicast_address[16]; 00489 00490 if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) { 00491 //Prefix not valid do not delete 00492 return; 00493 } 00494 // Unregister to link local all thread nodes multicast 00495 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 2); 00496 tr_debug("Free multicast address: %s", trace_ipv6(multicast_address)); 00497 //multicast_free_address(multicast_address); 00498 addr_remove_group(cur, multicast_address); 00499 00500 // Unregister to mesh local all thread nodes multicast 00501 thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); 00502 tr_debug("Free multicast address: %s", trace_ipv6(multicast_address)); 00503 //multicast_free_address(multicast_address); 00504 addr_remove_group(cur, multicast_address); 00505 } 00506 00507 void thread_end_device_mode_set(protocol_interface_info_entry_t *cur, bool sleepy) 00508 { 00509 if (sleepy) { 00510 cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; 00511 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false); 00512 } else { 00513 cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; 00514 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); 00515 } 00516 } 00517 00518 00519 int8_t nwk_thread_host_control(protocol_interface_info_entry_t *cur, net_host_mode_t mode, uint32_t delay) 00520 { 00521 int8_t ret_val = 0; 00522 //Check IF Bootsrap Ready and type is Host 00523 00524 if (cur == NULL || cur->rfd_poll_info == NULL) { 00525 return -1; 00526 } 00527 00528 nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info; 00529 switch (mode) { 00530 case NET_HOST_FAST_POLL_MODE: 00531 //fast mode 00532 //Check Host current sleep state 00533 if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) { 00534 tr_debug("Enable Fast poll mode. Init Poll timer and period"); 00535 thread_end_device_mode_set(cur, true); 00536 mac_poll_timer_trig(delay, cur); 00537 rf_ptr->nwk_app_poll_time = 300; 00538 rf_ptr->host_mode = NET_HOST_FAST_POLL_MODE; 00539 } 00540 break; 00541 00542 case NET_HOST_RX_ON_IDLE: 00543 // Non-sleep mode 00544 thread_end_device_mode_set(cur, false); 00545 rf_ptr->host_mode = NET_HOST_RX_ON_IDLE; 00546 break; 00547 00548 default: 00549 ret_val = -1; 00550 break; 00551 } 00552 00553 return ret_val; 00554 } 00555 00556 void thread_set_link_local_address(protocol_interface_info_entry_t *cur) 00557 { 00558 ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { 00559 if (memcmp(addr->address, ADDR_LINK_LOCAL_PREFIX, 8) == 0) { 00560 tr_debug("deleting address %s", trace_ipv6(addr->address)); 00561 ns_list_remove(&cur->ip_addresses, addr); 00562 ns_dyn_mem_free(addr); 00563 } 00564 } 00565 00566 /* Fix EUId64 also to start use 0*/ 00567 memcpy(cur->iid_eui64, cur->mac, 8); 00568 cur->iid_eui64[0] ^= 2; 00569 addr_interface_set_ll64(cur, NULL); 00570 } 00571 00572 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00573 { 00574 tr_debug("MAC SET Security Mode"); 00575 00576 if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE) || !(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) { 00577 return -1; 00578 } 00579 mac_helper_security_key_clean(cur); 00580 mac_helper_default_security_level_set(cur, 5); 00581 mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX); 00582 00583 cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY; 00584 cur->mac_parameters->mac_configured_sec_level = 5; 00585 cur->thread_info->masterSecretMaterial.historyKeyValid = false; 00586 cur->thread_info->masterSecretMaterial.valid_Info = true; 00587 // Update the guard timer value 00588 thread_key_guard_timer_calculate(cur, linkConfiguration, true); 00589 //Define KEY's 00590 thread_security_prev_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence); 00591 thread_security_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence); 00592 thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence); 00593 return 0; 00594 } 00595 00596 void thread_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator) 00597 { 00598 mlme_start_t start_req; 00599 memset(&start_req, 0, sizeof(mlme_start_t)); 00600 00601 cur->mac_parameters->pan_id = panid; 00602 cur->mac_parameters->mac_channel = channel; 00603 00604 start_req.PANId = panid; 00605 start_req.LogicalChannel = channel; 00606 start_req.BeaconOrder = 0x0f; 00607 start_req.SuperframeOrder = 0x0f; 00608 start_req.PANCoordinator = coordinator; 00609 00610 thread_discovery_responser_enable(cur->id, coordinator); 00611 00612 if (cur->mac_api) { 00613 cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void *)&start_req); 00614 } 00615 } 00616 00617 int thread_configuration_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, uint8_t *extended_random_mac) 00618 { 00619 ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); 00620 mac_helper_mac64_set(cur, extended_random_mac); 00621 thread_set_link_local_address(cur); 00622 00623 //SET Thread default here 00624 mac_helper_mac_mlme_max_retry_set(cur->id, THREAD_MAX_FRAME_RETRIES); 00625 00626 bool coordinator = (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER); 00627 thread_bootstrap_mac_activate(cur, channel, panid, coordinator); 00628 00629 mac_data_poll_init(cur); 00630 00631 return 0; 00632 } 00633 00634 int thread_configuration_6lowpan_activate(protocol_interface_info_entry_t *cur) 00635 { 00636 tr_debug("6lowpan configure"); 00637 cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION; 00638 cur->configure_flags |= INTERFACE_SECURITY_DEFINED; 00639 return 0; 00640 } 00641 00642 static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t *cur, const link_configuration_s *conf) 00643 { 00644 tr_debug("Updating ML addresses and prefix information."); 00645 uint8_t address[16]; 00646 00647 if (cur->thread_info->threadPrivatePrefixInfo.ulaValid && 00648 memcmp(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 00649 conf->mesh_local_ula_prefix, 8) != 0) { 00650 // Current prefix is valid and old vs. new different: update old addresses 00651 // Update the addresses in the neighbor cache (replace the old ULA prefix part) 00652 ns_list_foreach(ipv6_neighbour_t, entry, &cur->ipv6_neighbour_cache.list) { 00653 tr_debug("Neighbor cache address: %s", trace_ipv6(entry->ip_address)); 00654 if (bitsequal(entry->ip_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) { 00655 memcpy(entry->ip_address, conf->mesh_local_ula_prefix, 8); 00656 tr_debug("Updated to %s.", trace_ipv6(entry->ip_address)); 00657 } 00658 } 00659 00660 // Delete the ML64 address 00661 thread_delete_ml64_address(cur); 00662 00663 // Free previously registered multicast addresses 00664 thread_bootstrap_all_nodes_multicast_unregister(cur); 00665 00666 // In-place replace all other mesh local addresses... 00667 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 00668 tr_debug("IP address: %s", trace_ipv6(e->address)); 00669 if (bitsequal(e->address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) { 00670 memcpy(address, conf->mesh_local_ula_prefix, 8); 00671 memcpy(address + 8, e->address + 8, 8); 00672 tr_debug("Updated to: %s", trace_ipv6(address)); 00673 addr_add(cur, address, e->prefix_len, e->source, e->valid_lifetime, e->preferred_lifetime, true); 00674 addr_delete_entry(cur, e); 00675 } 00676 } 00677 } 00678 00679 // Set new ML-EID and ULA prefix 00680 uint8_t *ml_eid = thread_joiner_application_ml_eid_get(cur->id); 00681 memcpy(cur->iid_slaac, ml_eid, 8); 00682 00683 arm_thread_private_ula_prefix_set(cur, conf->mesh_local_ula_prefix); 00684 00685 // Generate new ML64 address 00686 thread_generate_ml64_address(cur); 00687 00688 // Register multicast addresses 00689 thread_bootstrap_all_nodes_multicast_register(cur); 00690 00691 // Register leader anycast address (if we are the leader) 00692 thread_router_bootstrap_anycast_address_register(cur); 00693 00694 thread_bootstrap_routing_activate(cur); 00695 } 00696 00697 int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00698 { 00699 tr_debug("thread configure"); 00700 00701 // Update existing mesh-local addresses and the ML prefix 00702 thread_bootstrap_ml_address_update(cur, linkConfiguration); 00703 00704 //Define Default Contexts 00705 lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true); 00706 00707 thread_bbr_commercial_route_update(cur); 00708 00709 blacklist_clear(); 00710 00711 blacklist_params_set( 00712 THREAD_BLACKLIST_ENTRY_LIFETIME, 00713 THREAD_BLACKLIST_TIMER_MAX_TIMEOUT, 00714 THREAD_BLACKLIST_TIMER_TIMEOUT, 00715 THREAD_BLACKLIST_ENTRY_MAX_NBR, 00716 THREAD_BLACKLIST_PURGE_NBR, 00717 THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT); 00718 00719 return 0; 00720 } 00721 00722 int thread_configuration_mle_activate(protocol_interface_info_entry_t *cur) 00723 { 00724 tr_debug("thread MLE configure"); 00725 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 00726 return 0; 00727 } 00728 00729 int thread_configuration_mle_disable(protocol_interface_info_entry_t *cur) 00730 { 00731 tr_debug("thread MLE disable"); 00732 mle_service_interface_receiver_handler_update(cur->id, NULL); 00733 return 0; 00734 } 00735 00736 static int thread_mle_service_register(protocol_interface_info_entry_t *cur, uint8_t *mac64) 00737 { 00738 if (mle_service_interface_register(cur->id, cur, thread_mle_parent_discover_receive_cb, mac64, 8) != 0) { 00739 tr_error("Mle Service init Fail"); 00740 return -1; 00741 } 00742 mle_service_set_frame_counter_check(true); 00743 mle_service_set_fragmented_msg_ll_security(true); 00744 return 0; 00745 } 00746 00747 int thread_link_configuration_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00748 { 00749 //Generate Beacon Payload from active configuration 00750 if (thread_beacon_create_payload(cur) != 0) { 00751 return -1; 00752 } 00753 00754 if (thread_configuration_mac_activate(cur, linkConfiguration->rfChannel, linkConfiguration->panId, thread_joiner_application_random_mac_get(cur->id))) { 00755 return -1; 00756 } 00757 00758 mac_helper_mac_device_description_pan_id_update(cur->id, linkConfiguration->panId); 00759 00760 thread_configuration_thread_activate(cur, linkConfiguration); 00761 thread_configuration_security_activate(cur, linkConfiguration); 00762 thread_configuration_6lowpan_activate(cur); 00763 return 0; 00764 } 00765 00766 int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp, uint16_t selected_channel) 00767 { 00768 uint8_t *ptr; 00769 uint8_t channel_tlv[3]; 00770 mle_message_timeout_params_t timeout; 00771 uint32_t keySequence; 00772 uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_DATASET_ANNOUNCE); 00773 if (buf_id == 0) { 00774 return -1; 00775 } 00776 00777 mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_NODES); 00778 00779 thread_management_get_current_keysequence(cur->id, &keySequence); 00780 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00781 mle_service_set_msg_link_layer_security_mode(buf_id, true); 00782 00783 ptr = mle_service_get_data_pointer(buf_id); 00784 00785 ptr = thread_meshcop_tlv_data_write_uint64(ptr, MLE_TYPE_ACTIVE_TIMESTAMP, timestamp); 00786 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MLE_TYPE_PANID, panid); 00787 channel_tlv[0] = channel_page; 00788 common_write_16_bit(channel, &channel_tlv[1]); 00789 ptr = thread_meshcop_tlv_data_write(ptr, MLE_TYPE_CHANNEL, 3, channel_tlv); 00790 00791 if (mle_service_update_length_by_ptr(buf_id, ptr) != 0) { 00792 tr_debug("Buffer overflow at message write"); 00793 } 00794 //SET packet channel 00795 mle_service_set_msg_rf_channel(buf_id, selected_channel); 00796 00797 timeout.retrans_max = 0; 00798 timeout.timeout_init = 0; 00799 timeout.timeout_max = 0; 00800 timeout.delay = MLE_NO_DELAY; 00801 00802 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00803 mle_service_set_msg_panid(buf_id, 0xffff); 00804 mle_service_send_message(buf_id); 00805 return 0; 00806 } 00807 static void thread_announce_ntf_cb(void *arg) 00808 { 00809 if (!arg) { 00810 return; 00811 } 00812 protocol_interface_info_entry_t *cur = arg; 00813 cur->thread_info->announcement_info->timer = NULL; 00814 thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00815 } 00816 00817 static void thread_announce_success_cb(void *arg) 00818 { 00819 // We come here when we have succesfully attached to announced channel and then we announce this back 00820 protocol_interface_info_entry_t *cur = arg; 00821 00822 if (!cur || !cur->thread_info->announcement_info) { 00823 return; 00824 } 00825 00826 cur->thread_info->announcement_info->timer = NULL; 00827 cur->thread_info->announcement_info->announce_success = false; 00828 thread_bootstrap_announcement_start(cur, cur->thread_info->announcement_info->channel_page, cur->thread_info->announcement_info->channel, 3, cur->thread_info->announcement_info->period); 00829 } 00830 00831 void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period) 00832 { 00833 if (!cur->thread_info->announcement_info) { 00834 cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t)); 00835 } 00836 if (!cur->thread_info->announcement_info) { 00837 return; 00838 } 00839 tr_info("Start announcement ch: %d", channel); 00840 cur->thread_info->announcement_info->channel = channel; 00841 cur->thread_info->announcement_info->period = period; 00842 cur->thread_info->announcement_info->channel_page = channel_page; 00843 cur->thread_info->announcement_info->count = count; 00844 cur->thread_info->announcement_info->timer = NULL; 00845 cur->thread_info->announcement_info->announce_success = false; 00846 cur->thread_info->announcement_info->timestamp = 0; 00847 thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00848 } 00849 void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp) 00850 { 00851 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 00852 00853 if (!linkConfiguration) { 00854 tr_error("No link configuration!"); 00855 return; 00856 } 00857 00858 tr_debug("Attach to new channel %u", channel); 00859 00860 /* 00861 * Save the old info and make a timer to announce it to old channels once if attachment is succesfull 00862 * When we receive attach fail 00863 */ 00864 if (!cur->thread_info->announcement_info) { 00865 cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t)); 00866 } 00867 if (!cur->thread_info->announcement_info) { 00868 return; 00869 } 00870 cur->thread_info->announcement_info->channel = linkConfiguration->rfChannel; 00871 cur->thread_info->announcement_info->channel_page = linkConfiguration->channel_page; 00872 cur->thread_info->announcement_info->panid = linkConfiguration->panId; 00873 cur->thread_info->announcement_info->count = 1; 00874 cur->thread_info->announcement_info->period = 1000; 00875 cur->thread_info->announcement_info->timestamp = timestamp; 00876 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb, 20000, cur); 00877 // TODO check timer value 00878 cur->thread_info->announcement_info->announce_success = true; 00879 linkConfiguration->channel_page = channel_page; 00880 linkConfiguration->rfChannel = channel; 00881 linkConfiguration->panId = panid; 00882 thread_joiner_application_link_configuration_store(cur->id, linkConfiguration); 00883 thread_bootstrap_reset_restart(cur->id); 00884 } 00885 00886 static const trickle_params_t thread_mpl_data_trickle_params = { 00887 .Imin = 1, /* 50ms */ 00888 .Imax = 2, /* 100ms */ 00889 .k = 0, 00890 .TimerExpirations = 2 /* MPL core knows to suppress to 0 for non-routers */ 00891 }; 00892 00893 static const trickle_params_t thread_mpl_control_trickle_params = { 00894 .Imin = 11, 00895 .Imax = 5 * 60 * 20, 00896 .k = 0, 00897 .TimerExpirations = 0 00898 }; 00899 00900 void thread_interface_init(protocol_interface_info_entry_t *cur) 00901 { 00902 thread_discovery_reset(cur->id); 00903 thread_routing_set_mesh_callbacks(cur); 00904 dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_EUI64_TYPE); 00905 dhcp_client_configure(cur->id, false, false, false); 00906 thread_management_client_init(cur->id); 00907 thread_bootstrap_address_registration_init(); 00908 cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT; 00909 cur->mpl_seed_set_entry_lifetime = 90; 00910 cur->mpl_proactive_forwarding = true; 00911 cur->mpl_control_trickle_params = thread_mpl_control_trickle_params; 00912 cur->mpl_data_trickle_params = thread_mpl_data_trickle_params; 00913 cur->mpl_seed = true; 00914 cur->mpl_treat_realm_domains_as_one = true; 00915 cur->if_ns_transmit = thread_nd_ns_transmit; 00916 cur->if_special_forwarding = thread_nd_special_forwarding; 00917 cur->if_snoop = thread_nd_snoop; 00918 cur->if_icmp_handler = thread_nd_icmp_handler; 00919 cur->ipv6_neighbour_cache.send_nud_probes = false; 00920 cur->ipv6_neighbour_cache.probe_avoided_routers = false; 00921 cur->ipv6_neighbour_cache.recv_addr_reg = true; 00922 cur->send_mld = false; 00923 cur->ip_multicast_as_mac_unicast_to_parent = true; 00924 if (!cur->thread_info->routerShortAddress) { 00925 cur->thread_info->routerShortAddress = 0xfffe; 00926 } 00927 if (cur->thread_info->thread_attach_scanned_parent) { 00928 mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id); 00929 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 00930 cur->thread_info->thread_attach_scanned_parent = NULL; 00931 } 00932 //Disable Always RPL 00933 rpl_control_remove_domain_from_interface(cur); 00934 mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL); 00935 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_NODES); 00936 cur->nwk_nd_re_scan_count = 5; 00937 00938 } 00939 00940 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur) 00941 { 00942 thread_routing_reset(&cur->thread_info->routing); 00943 mac_helper_mac16_address_set(cur, 0xffff); 00944 00945 if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) { 00946 tr_debug("Set ASPIRING Router Mode"); 00947 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_ROUTER; 00948 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 00949 } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST && 00950 cur->thread_info->end_device_link_synch) { 00951 tr_debug("Set FED Mode"); 00952 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_FULL_END_DEVICE; 00953 } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) { 00954 tr_debug("Set ASPIRING Sleepy Host Mode"); 00955 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE; 00956 //SET Sleepy Host To RX on Idle mode for bootsrap 00957 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 00958 cur->thread_info->childUpdateReqTimer = 0.8 * cur->thread_info->host_link_timeout; 00959 } else { 00960 tr_debug("Set End node Mode"); 00961 cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE; 00962 } 00963 00964 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00965 // set router neighbour cache 00966 ipv6_neighbour_cache_configure(THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SIZE, 00967 THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_SHORT_TERM, 00968 THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LONG_TERM, 00969 THREAD_ROUTER_IPV6_NEIGHBOUR_CACHE_LIFETIME); 00970 // set router destination cache 00971 ipv6_destination_cache_configure(THREAD_ROUTER_IPV6_DESTINATION_CACHE_SIZE, 00972 THREAD_ROUTER_IPV6_DESTINATION_CACHE_SHORT_TERM, 00973 THREAD_ROUTER_IPV6_DESTINATION_CACHE_LONG_TERM, 00974 THREAD_ROUTER_IPV6_DESTINATION_CACHE_LIFETIME); 00975 } else { 00976 // device is some sort of end device 00977 ipv6_neighbour_cache_configure(THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SIZE, 00978 THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_SHORT_TERM, 00979 THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LONG_TERM, 00980 THREAD_END_DEVICE_IPV6_NEIGHBOUR_CACHE_LIFETIME); 00981 00982 ipv6_destination_cache_configure(THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SIZE, 00983 THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_SHORT_TERM, 00984 THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LONG_TERM, 00985 THREAD_END_DEVICE_IPV6_DESTINATION_CACHE_LIFETIME); 00986 } 00987 00988 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 00989 } 00990 00991 int8_t thread_bootsrap_event_trig(thread_bootsrap_event_type_e event_type, int8_t Id, arm_library_event_priority_e priority) 00992 { 00993 arm_event_s event = { 00994 .receiver = Id, 00995 .sender = 0, 00996 .event_type = event_type, 00997 .priority = priority, 00998 }; 00999 return eventOS_event_send(&event); 01000 } 01001 01002 void thread_bootstrap_reset_restart(int8_t interface) 01003 { 01004 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); 01005 if (!cur) { 01006 return; 01007 } 01008 01009 if (cur->nwk_bootstrap_state == ER_MLE_SYNCH) { 01010 thread_network_synch_data_free(cur->id); 01011 } 01012 thread_nd_service_disable(interface); 01013 thread_routing_deactivate(&cur->thread_info->routing); 01014 //TODO: clear CoAP resending queue 01015 thread_bootsrap_event_trig(THREAD_BOOTSTRAP_RESET, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01016 } 01017 01018 void thread_tasklet(arm_event_s *event) 01019 { 01020 01021 protocol_interface_info_entry_t *cur = 0; 01022 thread_bootsrap_event_type_e event_type; 01023 event_type = (thread_bootsrap_event_type_e)event->event_type; 01024 cur = protocol_stack_interface_info_get_by_bootstrap_id(event->receiver); 01025 if (!cur) { 01026 tr_debug("Thread task unknown"); 01027 return; 01028 } 01029 01030 switch (event_type) { 01031 case THREAD_INIT_EVENT: 01032 tr_debug_extra("Thread SM THREAD_INIT_EVENT"); 01033 tr_debug("Thread task Init"); 01034 break; 01035 01036 case THREAD_BOOTSTRAP_RESET: 01037 //Reset Current Thread state 01038 tr_debug_extra("Thread SM THREAD_BOOTSTRAP_RESET"); 01039 if (thread_bootstrap_reset(cur) == 0) { 01040 tr_debug("Thread Attached"); 01041 } else { 01042 tr_debug("Stop Bootsrap and send event"); 01043 } 01044 break; 01045 01046 case THREAD_ATTACH_READY: 01047 tr_debug_extra("Thread SM THREAD_ATTACH_READY"); 01048 thread_bootstrap_attached_finish(cur); 01049 break; 01050 case THREAD_ATTACH_UPGRADE_REED: 01051 tr_debug_extra("Thread SM THREAD_ATTACH_UPGRADE_REED"); 01052 if (thread_router_bootstrap_child_count_get(cur) > 0) { 01053 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_PARENT_PARTITION_CHANGE); 01054 } else { 01055 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_TOO_FEW_ROUTERS); 01056 } 01057 01058 break; 01059 01060 case THREAD_ATTACH_DOWNGRADE_ROUTER: 01061 tr_debug_extra("Thread SM THREAD_ATTACH_DOWNGRADE_ROUTER"); 01062 thread_bootstrap_attach_start(cur->id, THREAD_REATTACH_REED); 01063 break; 01064 01065 case THREAD_ATTACH_ACTIVE_ROUTER: 01066 tr_debug_extra("Thread SM THREAD_ATTACH_ACTIVE_ROUTER"); 01067 thread_bootstrap_all_nodes_multicast_register(cur); 01068 thread_router_bootstrap_anycast_address_register(cur); 01069 thread_router_bootstrap_active_router_attach(cur); 01070 thread_bootstrap_child_id_request(cur); 01071 if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) { 01072 // publish our services to allow leader to remove old ones 01073 thread_border_router_publish(cur->id); 01074 } 01075 thread_router_bootstrap_address_change_notify_send(cur); 01076 // Validate network data after a short period 01077 thread_border_router_resubmit_timer_set(cur->id, 5); 01078 break; 01079 case THREAD_ATTACH_ROUTER_ID_GET_FAIL: 01080 tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_GET_FAIL"); 01081 tr_debug("Thread Router Id request Fail"); 01082 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01083 cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 01084 thread_router_bootstrap_child_information_clear(cur); 01085 thread_router_bootstrap_reed_advertisements_start(cur); 01086 thread_router_bootstrap_child_id_reject(cur); 01087 break; 01088 01089 case THREAD_ATTACH_ROUTER_ID_RELEASED: 01090 tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_RELEASED"); 01091 if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) { 01092 // publish our services to allow leader to remove old ones 01093 thread_border_router_publish(cur->id); 01094 } 01095 break; 01096 01097 case THREAD_CHILD_ID_REQUEST: 01098 tr_debug_extra("Thread SM THREAD_CHILD_ID_REQUEST"); 01099 thread_router_bootstrap_child_id_handler(cur); 01100 break; 01101 01102 case THREAD_CHILD_UPDATE: 01103 tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); 01104 thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); 01105 break; 01106 case THREAD_ANNOUNCE_ACTIVE: { 01107 tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); 01108 01109 if (cur->thread_info->announcement_info->count > 0) { 01110 cur->thread_info->announcement_info->count--; 01111 01112 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 01113 if (!linkConfiguration) { 01114 tr_error("No link configuration!"); 01115 break; 01116 } 01117 01118 // New timeout needed 01119 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_ntf_cb, cur->thread_info->announcement_info->period, cur); 01120 01121 // Send announce_ntf 01122 thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, cur->thread_info->announcement_info->channel); 01123 } else { 01124 // Last call, delete announcement info 01125 ns_dyn_mem_free(cur->thread_info->announcement_info); 01126 cur->thread_info->announcement_info = NULL; 01127 } 01128 01129 break; 01130 } 01131 01132 default: 01133 break; 01134 } 01135 } 01136 01137 01138 int thread_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur) 01139 { 01140 if (cur->bootStrapId < 0) { 01141 cur->bootStrapId = eventOS_event_handler_create(&thread_tasklet, THREAD_INIT_EVENT); 01142 tr_debug("Allocate Thread Tasklet"); 01143 } 01144 if (cur->bootStrapId >= 0) { 01145 return 0; 01146 } 01147 return -1; 01148 } 01149 01150 int thread_proxy_validate(int8_t interface_id, uint8_t *addrerss) 01151 { 01152 ipv6_route_t *route; 01153 route = ipv6_route_choose_next_hop(addrerss, interface_id, NULL); 01154 if (!route) { 01155 return -1; 01156 } 01157 01158 if (route->prefix_len < 128 || !route->on_link) { 01159 return -1; 01160 } 01161 01162 return 0; 01163 } 01164 01165 void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) 01166 { 01167 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01168 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; 01169 01170 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 01171 cur->ip_multicast_as_mac_unicast_to_parent = false; 01172 cur->ip_forwarding = true; 01173 } else { 01174 cur->ip_multicast_as_mac_unicast_to_parent = true; 01175 cur->ip_forwarding = false; 01176 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01177 /* REED should be able to IP forward */ 01178 cur->ip_forwarding = true; 01179 } else { 01180 cur->ip_forwarding = false; 01181 } 01182 } 01183 01184 tr_info("Set forwarding: ip=%d, multicast=%d", cur->ip_forwarding, thread_i_am_router(cur)); 01185 01186 if (cur->ip_forwarding) { 01187 addr_add_router_groups(cur); 01188 } 01189 // Bizarrely, Thread needs Realm-All-Routers active in FEDs for address resolution 01190 if (cur->ip_forwarding || cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 01191 addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS); 01192 } 01193 01194 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01195 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) { 01196 thread_router_bootstrap_reed_advertisements_start(cur); 01197 } 01198 01199 thread_bootstrap_mac_activate(cur, cur->mac_parameters->mac_channel, cur->mac_parameters->pan_id, true); 01200 01201 if (nd_proxy_downstream_interface_register(cur->id, thread_proxy_validate, thread_bbr_proxy_state_update) != 0) { 01202 tr_debug("mesh proxy register fail"); 01203 } 01204 } 01205 01206 if (cur->thread_info->leader_private_data) { 01207 // Generate network data from network data structures 01208 thread_leader_service_generate_network_data(cur); 01209 } 01210 01211 if (thread_addresses_needs_to_be_registered(cur)) { 01212 thread_info(cur)->childUpdateReqTimer = 1; 01213 } 01214 01215 cur->bootsrap_state_machine_cnt = 0; 01216 mac_data_poll_protocol_poll_mode_decrement(cur); 01217 } 01218 01219 void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur) 01220 { 01221 mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; 01222 01223 ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { 01224 if (!thread_addr_is_equal_or_child(cur->thread_info->routerShortAddress, cur_entry->mac16)) { 01225 tr_debug("Free ID %x", cur_entry->mac16); 01226 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry); 01227 } 01228 } 01229 } 01230 01231 void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur) 01232 { 01233 mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; 01234 01235 if (thread_i_am_router(cur)) { 01236 return; 01237 } 01238 01239 if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 01240 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 01241 return; 01242 } 01243 01244 if (!thread_info(cur)->thread_endnode_parent) { 01245 return; 01246 } 01247 ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { 01248 // do not remove parent entry 01249 if (memcmp(cur_entry->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) != 0) { 01250 tr_debug("Free short addr: %x", cur_entry->mac16); 01251 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry); 01252 } 01253 } 01254 } 01255 01256 void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur) 01257 { 01258 uint8_t static_address[16]; 01259 //Delete old ULA16 01260 memcpy(static_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01261 memcpy(&static_address[8], ADDR_SHORT_ADR_SUFFIC, 6); 01262 common_write_16_bit(mac_helper_mac16_address_get(cur), &static_address[14]); 01263 addr_delete(cur, static_address); 01264 mac_helper_mac16_address_set(cur, 0xffff); 01265 01266 } 01267 01268 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state) 01269 { 01270 01271 protocol_interface_info_entry_t *cur; 01272 01273 cur = protocol_stack_interface_info_get_by_id(interface_id); 01274 if (!cur || !cur->thread_info) { 01275 return -1; 01276 } 01277 //Trigger the bootstrap 01278 01279 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01280 01281 switch (state) { 01282 case THREAD_NORMAL_ATTACH: 01283 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01284 mac_helper_default_security_level_set(cur, cur->mac_parameters->mac_configured_sec_level); 01285 mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX); 01286 break; 01287 01288 case THREAD_REATTACH: 01289 tr_debug("Thread ReAttach"); 01290 //save the current partition id and sequence number before trying reattach 01291 cur->thread_info->previous_partition_info.partitionId = cur->thread_info->thread_leader_data->partitionId; 01292 cur->thread_info->previous_partition_info.weighting = cur->thread_info->thread_leader_data->weighting; 01293 cur->thread_info->previous_partition_info.idSequence = cur->thread_info->routing.router_id_sequence; 01294 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01295 if (cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY) { 01296 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH; 01297 } 01298 break; 01299 case THREAD_PARTITION_MERGE: 01300 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01301 break; 01302 case THREAD_ANY_ATTACH: 01303 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01304 cur->thread_info->thread_attached_state = THREAD_STATE_ATTACH_ANY; 01305 break; 01306 01307 case THREAD_REATTACH_REED: 01308 cur->thread_info->releaseRouterId = true; 01309 cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur); 01310 01311 if (cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY) { 01312 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH; 01313 } 01314 break; 01315 } 01316 01317 // Set RX on idle 01318 thread_end_device_mode_set(cur, false); 01319 cur->nwk_nd_re_scan_count = 0; 01320 cur->nwk_bootstrap_state = ER_SCAN; 01321 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 10); 01322 return 0; 01323 } 01324 01325 static void thread_bootsrap_network_discovery_failure(int8_t interface_id) 01326 { 01327 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01328 if (!cur || !cur->thread_info) { 01329 return; 01330 } 01331 //TODO we should send 3 in burst of 0.1 - 0.6 seconds and then do the exponential backup of 5s -- 80s 01332 uint32_t backof_delay = cur->nwk_nd_re_scan_count * 2; 01333 if (backof_delay > 600) { 01334 backof_delay = 600; //TODO test this and check guess this is 100ms ticks 01335 } 01336 01337 tr_debug("Continue network scan"); 01338 cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01339 cur->bootsrap_state_machine_cnt = backof_delay + randLIB_get_random_in_range(1, 6); 01340 } 01341 01342 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur) 01343 { 01344 if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH) { 01345 tr_debug("ReAttach Fail - retry"); 01346 thread_bootstrap_attach_start(cur->id, THREAD_REATTACH); 01347 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH_RETRY; 01348 } else if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY) { 01349 tr_warn("ReAttach Fail"); 01350 thread_bootstrap_attach_start(cur->id, THREAD_ANY_ATTACH); 01351 } else { 01352 if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) { 01353 bootsrap_next_state_kick(ER_BOOTSTRAP_LEADER_UP, cur); 01354 } else { 01355 bootsrap_next_state_kick(ER_BOOTSTRAP_NEW_FRAGMENT_START, cur); 01356 } 01357 } 01358 } 01359 static int8_t thread_bootstrap_attempt_attach_with_pending_set(protocol_interface_info_entry_t *cur) 01360 { 01361 tr_debug("Attempting to attach with pending set"); 01362 uint32_t pending_delay_timer = thread_joiner_application_pending_config_timeout_get(cur->id); 01363 if (pending_delay_timer > 0 && thread_joiner_application_pending_delay_timer_in_sync(cur->id)) { 01364 tr_debug("We have a pending delay timer running"); 01365 //we already have a pending set that can be activated so return 01366 return -1; 01367 } 01368 01369 if (!thread_joiner_application_pending_config_exists(cur->id)) { 01370 tr_debug("no pending configuration found after reset"); 01371 return -1; 01372 } 01373 01374 if (thread_joiner_application_old_config_exists(cur->id)) { 01375 //there is an existing old configuration so attempt to attach with it and set the pending timer to expire 01376 thread_joiner_application_old_config_activate(cur->id); 01377 thread_joiner_application_old_config_delete(cur->id); 01378 thread_joiner_application_pending_config_enable(cur->id, 20000); 01379 } else { 01380 thread_joiner_pending_config_activate(cur->id); 01381 } 01382 01383 return 0; 01384 } 01385 01386 static void thread_bootstrap_orphan_scan_ready_cb(struct protocol_interface_info_entry *cur_interface, announce_discovery_response_t *discover_response) 01387 { 01388 01389 if (!discover_response) { 01390 thread_bootstrap_orphan_scan_start(cur_interface); 01391 return; 01392 } 01393 01394 link_configuration_s *link_configuration = thread_joiner_application_get_config(cur_interface->id); 01395 01396 if (!link_configuration) { 01397 tr_debug("no link configuration found after reset"); 01398 return; 01399 } 01400 01401 tr_debug("New configuration received channel %u, %x", discover_response->channel, discover_response->pan_id); 01402 link_configuration->panId = discover_response->pan_id; 01403 link_configuration->rfChannel = discover_response->channel; 01404 link_configuration->channel_page = 0; 01405 cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01406 cur_interface->bootsrap_state_machine_cnt = 1; 01407 ns_dyn_mem_free(discover_response); 01408 } 01409 01410 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur) 01411 { 01412 thread_announce_discover_reques_t scan_req; 01413 //default channel mask for channels 11 to 26 01414 scan_req.channel_mask = 0x001fffe0; 01415 #ifdef THREAD_THCI_SUPPORT 01416 //use active operational dataset's channel mask if available 01417 link_configuration_s *link_configuration = thread_joiner_application_get_config(cur->id); 01418 if (!link_configuration) { 01419 return; 01420 } 01421 scan_req.channel_mask = common_read_32_bit(link_configuration->channel_mask); 01422 //the current channel is added to the mask. 01423 scan_req.channel_mask |= (0x80000000 >> link_configuration->rfChannel); 01424 #endif 01425 scan_req.pan_id = cur->mac_parameters->pan_id; 01426 scan_req.active_timestamp = 0; 01427 scan_req.active_timestamp |= MESHCOP_TLV_ACTIVE_TIME_STAMP_U_BIT; 01428 01429 if (thread_discovery_announce_network_scan(cur->id, &scan_req, thread_bootstrap_orphan_scan_ready_cb) != 0) { 01430 01431 tr_debug("announce discover start fail"); 01432 thread_bootstrap_attach_start(cur->id, THREAD_NORMAL_ATTACH); 01433 } else { 01434 tr_debug("Orphan Host start announce scan"); 01435 } 01436 return; 01437 } 01438 01439 void thread_bootstrap_connection_error(int8_t interface_id, nwk_connect_error_types errorType, uint8_t *LinkId) 01440 { 01441 (void)LinkId; 01442 protocol_interface_info_entry_t *cur; 01443 01444 switch (errorType) { 01445 case CON_ERROR_POLL: 01446 case CON_PARENT_CONNECT_DOWN: 01447 thread_bootstrap_reset_restart(interface_id); 01448 break; 01449 01450 case CON_ERROR_LINK_TX_FAIL: 01451 //thread_mle_challenge_trig(interface_id,LinkId); 01452 break; 01453 01454 case CON_ERROR_NETWORK_ATTACH_FAIL: 01455 cur = protocol_stack_interface_info_get_by_id(interface_id); 01456 if (!cur || !cur->thread_info) { 01457 break; 01458 } 01459 if (thread_bootstrap_attempt_attach_with_pending_set(cur) == 0) { 01460 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH); 01461 break; 01462 } 01463 01464 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timer && 01465 cur->thread_info->announcement_info->announce_success) { 01466 // Attachment to announce failed we return to previous channel 01467 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 01468 01469 if (linkConfiguration) { 01470 linkConfiguration->rfChannel = cur->thread_info->announcement_info->channel; 01471 linkConfiguration->channel_page = cur->thread_info->announcement_info->channel_page; 01472 linkConfiguration->panId = cur->thread_info->announcement_info->panid; 01473 thread_joiner_application_link_configuration_store(cur->id, linkConfiguration); 01474 } else { 01475 tr_error("No link configuration!"); 01476 } 01477 //set announce success flag to false because attach to new channel failed 01478 cur->thread_info->announcement_info->announce_success = false; 01479 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH); 01480 01481 break; 01482 } 01483 01484 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01485 if (!thread_router_bootstrap_routing_allowed(cur)) { 01486 thread_discovery_responser_enable(cur->id, false); 01487 thread_bootstrap_orphan_scan_start(cur); 01488 } else { 01489 thread_bootstrap_generate_leader_and_link(cur); 01490 } 01491 } else { 01492 thread_bootstrap_orphan_scan_start(cur); 01493 } 01494 break; 01495 01496 case CON_ERROR_NO_THREAD_NETWORK_AVAILABLE: 01497 thread_bootsrap_network_discovery_failure(interface_id); 01498 break; 01499 case CON_ERROR_PARTITION_MERGE: 01500 thread_bootstrap_attach_start(interface_id, THREAD_PARTITION_MERGE); 01501 break; 01502 case CON_ERROR_NETWORK_REATTACH: 01503 thread_bootstrap_attach_start(interface_id, THREAD_REATTACH); 01504 break; 01505 case CON_ERROR_NEIGHBOR_UNREACHABLE: 01506 01507 break; 01508 case CON_ERROR_NETWORK_KICK: 01509 thread_bootstrap_reset_restart(interface_id); 01510 break; 01511 } 01512 } 01513 01514 void thread_interface_up(protocol_interface_info_entry_t *cur) 01515 { 01516 thread_interface_init(cur); 01517 thread_interface_bootsrap_mode_init(cur); 01518 cur->nwk_nd_re_scan_count = 0; 01519 } 01520 01521 int thread_bootstrap_reset(protocol_interface_info_entry_t *cur) 01522 { 01523 if (!cur || !cur->thread_info || (cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) { 01524 return -1; 01525 } 01526 01527 if (cur->thread_info->thread_endnode_parent) { 01528 ns_dyn_mem_free(cur->thread_info->thread_endnode_parent); 01529 cur->thread_info->thread_endnode_parent = NULL; 01530 } 01531 01532 neighbor_cache_flush(&cur->neigh_cache); 01533 thread_bootstrap_stop(cur); 01534 mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur)); 01535 cur->bootsrap_state_machine_cnt = 0; 01536 mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params); 01537 //tr_debug( "--> idle"); 01538 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 01539 rpl_control_remove_domain_from_interface(cur); 01540 protocol_core_interface_info_reset(cur); 01541 mac_data_poll_disable(cur); 01542 01543 //Prepare start Again 01544 01545 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; //Set Active Bootsrap 01546 cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; //Clear Bind 01547 protocol_6lowpan_interface_common_init(cur); 01548 addr_interface_set_ll64(cur, NULL); 01549 thread_interface_up(cur); 01550 01551 cur->nwk_mode = ARM_NWK_GP_IP_MODE; 01552 cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01553 cur->nwk_nd_re_scan_count = 0; 01554 if (cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY) { 01555 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01556 } 01557 cur->ipv6_neighbour_cache.send_nud_probes = false; //Disable NUD probing 01558 cur->ipv6_neighbour_cache.probe_avoided_routers = false; 01559 cur->ip_multicast_as_mac_unicast_to_parent = true; 01560 //Define Default Contexts 01561 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 01562 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01563 } 01564 thread_anycast_address_policy_update(cur->thread_info, true); 01565 thread_bootstrap_state_machine(cur); 01566 return 0; 01567 } 01568 01569 void thread_generate_ml64_address(protocol_interface_info_entry_t *cur) 01570 { 01571 if_address_entry_t *def_address = NULL; 01572 uint8_t ula[16]; 01573 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01574 //GENERATE ML-EID64 01575 memcpy(&ula[8], cur->iid_slaac, 8); 01576 def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true); 01577 if (def_address) { 01578 tr_debug("Generated UL64: %s", trace_ipv6(ula)); 01579 } 01580 } 01581 01582 void thread_delete_ml64_address(protocol_interface_info_entry_t *cur) 01583 { 01584 uint8_t ula[16]; 01585 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01586 memcpy(&ula[8], cur->iid_slaac, 8); 01587 addr_delete(cur, ula); 01588 01589 } 01590 01591 void thread_generate_ml16_address(protocol_interface_info_entry_t *cur) 01592 { 01593 if_address_entry_t *def_address = NULL; 01594 uint8_t ula[16]; 01595 uint16_t euid16 = mac_helper_mac16_address_get(cur); 01596 if (euid16 == 0xffff) { // Safe guard 01597 tr_debug("Do NOT generate ML16, mac16=%u", euid16); 01598 return; 01599 } 01600 //GENERATE ML-16 01601 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01602 memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6); 01603 common_write_16_bit(euid16, &ula[14]); 01604 01605 def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true); 01606 if (def_address) { 01607 tr_debug("Generated ML16: %s", trace_ipv6(ula)); 01608 cur->global_address_available = true; 01609 } 01610 } 01611 01612 void thread_delete_ml16_addresses(protocol_interface_info_entry_t *cur) 01613 { 01614 uint8_t ula[16] = {0}; 01615 memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 01616 memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6); 01617 addr_delete_matching(cur, ula, 112, ADDR_SOURCE_UNKNOWN); 01618 } 01619 01620 void thread_bootstrap_update_ml16_address(protocol_interface_info_entry_t *cur, uint16_t mac16) 01621 { 01622 thread_delete_ml16_addresses(cur); 01623 mac_helper_mac16_address_set(cur, mac16); 01624 thread_generate_ml16_address(cur); 01625 thread_router_bootstrap_anycast_address_register(cur); 01626 } 01627 static void thread_meshlocal_route_set(protocol_interface_info_entry_t *cur) 01628 { 01629 cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE; 01630 if (ipv6_route_add(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64, cur->id, NULL, ROUTE_THREAD, 0xffffffff, 0) == NULL) { 01631 tr_error("fail to add route"); 01632 } 01633 } 01634 01635 void thread_bootstrap_attached_ready(protocol_interface_info_entry_t *cur) 01636 { 01637 thread_bootsrap_event_trig(THREAD_ATTACH_READY, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01638 } 01639 01640 void thread_bootstrap_attached_downgrade_router(protocol_interface_info_entry_t *cur) 01641 { 01642 thread_bootsrap_event_trig(THREAD_ATTACH_DOWNGRADE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01643 } 01644 01645 void thread_bootstrap_attched_upgrade_reed(protocol_interface_info_entry_t *cur) 01646 { 01647 thread_bootsrap_event_trig(THREAD_ATTACH_UPGRADE_REED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01648 } 01649 01650 void thread_bootstrap_attached_active_router(protocol_interface_info_entry_t *cur) 01651 { 01652 thread_bootsrap_event_trig(THREAD_ATTACH_ACTIVE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01653 } 01654 01655 void thread_bootstrap_router_id_release_ready(protocol_interface_info_entry_t *cur) 01656 { 01657 thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_RELEASED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01658 } 01659 01660 void thread_bootstrap_router_id_get_fail(protocol_interface_info_entry_t *cur) 01661 { 01662 thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_GET_FAIL, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01663 } 01664 01665 int8_t thread_bootstrap_child_id_request(protocol_interface_info_entry_t *cur) 01666 { 01667 return thread_bootsrap_event_trig(THREAD_CHILD_ID_REQUEST, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01668 } 01669 01670 void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur) 01671 { 01672 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE || 01673 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01674 thread_meshlocal_route_set(cur); 01675 // FEDs and routers (REEDs) perform their own address resolution 01676 thread_nd_service_activate(cur->id); 01677 } else { 01678 thread_nd_client_service_activate(cur->id); 01679 thread_child_set_default_route(cur); 01680 } 01681 } 01682 01683 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) 01684 { 01685 cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 01686 cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; 01687 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 01688 cur->bootsrap_state_machine_cnt = 10; 01689 cur->thread_info->routerIdRequested = false; 01690 cur->thread_info->networkDataRequested = false; 01691 clear_power_state(ICMP_ACTIVE); 01692 01693 //Free scanned Result 01694 if (cur->thread_info->thread_attach_scanned_parent) { 01695 mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id); 01696 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 01697 cur->thread_info->thread_attach_scanned_parent = NULL; 01698 } 01699 01700 // Make local/nwk data check after 5s 01701 thread_border_router_resubmit_timer_set(cur->id, 5); 01702 //Generate UL16 01703 thread_generate_ml16_address(cur); 01704 //GENERATE ML-EID64 01705 thread_generate_ml64_address(cur); 01706 thread_bootstrap_routing_activate(cur); 01707 thread_bootstrap_network_data_update(cur); 01708 // After successful attach if there is announcement info present, send announcement back to previous channel 01709 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->announce_success == false) { 01710 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb, 20000, cur); 01711 } 01712 thread_configuration_mle_activate(cur); 01713 01714 if (cur->thread_info->releaseRouterId) { 01715 thread_router_bootstrap_router_id_release(cur); 01716 } 01717 uint8_t *parent_mac_addr = NULL; 01718 if (cur->thread_info->thread_endnode_parent) { 01719 parent_mac_addr = cur->thread_info->thread_endnode_parent->mac64; 01720 } 01721 thread_nvm_store_link_info_write(parent_mac_addr, mac_helper_mac16_address_get(cur)); 01722 thread_bootstrap_ready(cur); 01723 01724 if (thread_is_router_addr(mac_helper_mac16_address_get(cur))) { 01725 // Attached as router Trigger routter attach 01726 tr_info("Attaching directly to router"); 01727 thread_bootstrap_attached_active_router(cur); 01728 } 01729 } 01730 01731 //This function is for Thread Parent scan callback 01732 bool thread_network_data_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 01733 { 01734 protocol_interface_info_entry_t *cur; 01735 (void)msgId; 01736 01737 cur = protocol_stack_interface_info_get_by_id(interface_id); 01738 if (!cur || !cur->thread_info) { 01739 return false; 01740 } 01741 01742 /* If network data is not received, send again */ 01743 if (thread_info(cur)->networkDataRequested && !usedAllRetries) { 01744 return true; 01745 } 01746 01747 if (cur->thread_info->leader_synced) { 01748 if (usedAllRetries) { 01749 // could not learn network data from neighbour, everyone must reregister 01750 cur->thread_info->leader_synced = false; 01751 thread_leader_service_network_data_changed(cur, true, true); 01752 return false; 01753 } else { 01754 tr_debug("retrying as leader data not yet synced"); 01755 return true; 01756 } 01757 } 01758 01759 // if REED fails to get updated network data, it reattaches 01760 if (thread_info(cur)->networkDataRequested && !thread_attach_active_router(cur) && usedAllRetries) { 01761 thread_bootstrap_reset_restart(interface_id); 01762 } 01763 01764 thread_info(cur)->networkDataRequested = false; 01765 mac_data_poll_protocol_poll_mode_decrement(cur); 01766 return false; 01767 } 01768 01769 01770 bool thread_tlv_request(int8_t interface_id, uint8_t *address, bool delayed_message, uint8_t *req_tlv, uint8_t req_len) 01771 { 01772 mle_message_timeout_params_t timeout; 01773 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01774 uint16_t buf_id; 01775 01776 buf_id = mle_service_msg_allocate(interface_id, 32 + 20 + thread_leader_data_tlv_size(cur), false, MLE_COMMAND_DATA_REQUEST); 01777 01778 if (!cur || buf_id == 0) { 01779 return false; 01780 } 01781 01782 uint8_t *ptr = mle_service_get_data_pointer(buf_id); 01783 ptr = mle_tlv_req_tlv(ptr, req_tlv, req_len); 01784 01785 //SET Leader Data 01786 ptr = thread_leader_data_tlv_write(ptr, cur); 01787 01788 ptr = thread_active_timestamp_write(cur, ptr); 01789 01790 ptr = thread_pending_timestamp_write(cur, ptr); 01791 01792 if (mle_service_update_length_by_ptr(buf_id, ptr) != 0) { 01793 tr_debug("Buffer overflow at message write"); 01794 } 01795 timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; 01796 timeout.timeout_init = 1; 01797 timeout.timeout_max = 3; 01798 if (delayed_message) { 01799 timeout.delay = MLE_STANDARD_RESPONSE_DELAY; 01800 } else { 01801 timeout.delay = MLE_NO_DELAY; 01802 } 01803 mac_data_poll_init_protocol_poll(cur); 01804 mle_service_set_packet_callback(buf_id, thread_network_data_timeout); 01805 mle_service_set_msg_destination_address(buf_id, address); 01806 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 01807 //Set Security 01808 uint32_t keySequence; 01809 thread_management_get_current_keysequence(cur->id, &keySequence); 01810 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 01811 mle_service_send_message(buf_id); 01812 return true; 01813 } 01814 01815 void thread_bootstrap_parent_network_data_request(protocol_interface_info_entry_t *cur, bool delay_request) 01816 { 01817 uint8_t dst_address[16]; 01818 memcpy(dst_address, ADDR_LINK_LOCAL_PREFIX, 8); 01819 memcpy(&dst_address[8], thread_info(cur)->thread_endnode_parent->mac64, 8); 01820 dst_address[8] ^= 2; 01821 thread_network_data_request_send(cur, dst_address, delay_request); 01822 } 01823 01824 void thread_parent_scan(protocol_interface_info_entry_t *cur) 01825 { 01826 cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER; 01827 cur->nwk_nd_re_scan_count = 0; 01828 cur->nwk_bootstrap_state = ER_SCAN; 01829 cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(5, 15); 01830 nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); 01831 } 01832 01833 void thread_bootstrap_joiner_application_commission_done_cb(int8_t interface_id) 01834 { 01835 protocol_interface_info_entry_t *interface; 01836 interface = protocol_stack_interface_info_get_by_id(interface_id); 01837 if (!interface) { 01838 return; 01839 } 01840 tr_debug("Commission Ready trig bootsrap to starting from init again"); 01841 interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01842 interface->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 4); 01843 } 01844 01845 static int compare_steering_and_joiner_bloom(uint8_t *steering_bloom, uint8_t *joiner_bloom, uint8_t steering_tlv_length) 01846 { 01847 //make sure s bit is not checked 01848 int loop_iterator; 01849 tr_debug("joiner bloom : %s", trace_array(joiner_bloom, steering_tlv_length)); 01850 tr_debug("steering bloom : %s", trace_array(steering_bloom, steering_tlv_length)); 01851 for (loop_iterator = 0; loop_iterator < steering_tlv_length; loop_iterator++) { 01852 if ((joiner_bloom[loop_iterator] != (joiner_bloom[loop_iterator] & steering_bloom[loop_iterator]))) { 01853 thci_trace("joinerDiscoveryFailedFiltered"); 01854 return 0; 01855 } 01856 } 01857 return 1; 01858 } 01859 01860 static bool thread_route_possible_add(thread_attach_device_mode_e threadMode) 01861 { 01862 bool addRoute; 01863 if (threadMode == THREAD_DEVICE_MODE_ROUTER || 01864 threadMode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 01865 addRoute = true; 01866 } else { 01867 addRoute = false; 01868 } 01869 01870 return addRoute; 01871 } 01872 01873 static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) 01874 { 01875 if (register_status) { 01876 tr_debug("Get Address %s From %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); 01877 } else { 01878 tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); 01879 if (prefix && dhcp_addr) { 01880 tr_debug("Delete Current Server data"); 01881 dhcp_client_global_address_delete(interface, dhcp_addr, prefix); 01882 } 01883 } 01884 } 01885 01886 bool thread_dhcpv6_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list) 01887 { 01888 bool addressReady = false; 01889 ns_list_foreach(if_address_entry_t, entry, list) { 01890 if (memcmp(entry->address, prefixPtr, 8) == 0) { 01891 addressReady = true; 01892 break; 01893 } 01894 } 01895 return addressReady; 01896 } 01897 01898 static int thread_bloom_and_compare(uint8_t *steering_data_ptr, uint8_t steering_data_length, uint8_t *eui64, uint8_t eui64_length) 01899 { 01900 if (steering_data_length == 0 || steering_data_length > 16) { 01901 return 0; 01902 } 01903 01904 uint8_t joiner_bloom_calculated[16] = {0}; 01905 uint8_t mac_extended_address[8]; 01906 01907 ns_sha256_nbits(eui64, eui64_length, mac_extended_address, 64); 01908 mac_extended_address[0] |= 2; //local administered bit is set 01909 01910 thread_beacon_calculate_bloom_filter(joiner_bloom_calculated, steering_data_length, mac_extended_address, 8); 01911 01912 return compare_steering_and_joiner_bloom(steering_data_ptr, joiner_bloom_calculated, steering_data_length); 01913 } 01914 01915 static void thread_network_select_by_steering_data(device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response) 01916 { 01917 ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) { 01918 01919 if (!thread_bloom_and_compare(cur_class->steering_data, cur_class->steering_data_valid, device_configuration_ptr->eui64, 8)) { 01920 ns_list_remove(discover_response, cur_class); 01921 ns_dyn_mem_free(cur_class); 01922 } 01923 01924 } 01925 } 01926 01927 static void thread_network_select(struct protocol_interface_info_entry *interface_ptr, device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response) 01928 { 01929 (void) interface_ptr; 01930 01931 discovery_response_list_t *discovered_network_ptr = thread_ccm_network_select(interface_ptr, discover_response); 01932 01933 /* If network found */ 01934 if (discovered_network_ptr) { 01935 /* Clear other networks from list */ 01936 ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) { 01937 if (cur_class != discovered_network_ptr) { 01938 ns_list_remove(discover_response, cur_class); 01939 ns_dyn_mem_free(cur_class); 01940 } 01941 } 01942 } else { 01943 thread_network_select_by_steering_data(device_configuration_ptr, discover_response); 01944 } 01945 } 01946 01947 void thread_bootsrap_discovery_ready_cb(struct protocol_interface_info_entry *cur_interface, thread_nwk_discovery_response_list_t *discover_response) 01948 { 01949 device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id); 01950 if (!device_configuration_ptr) { 01951 tr_error("Mac scan confirm:Unknow Interface"); 01952 thci_trace("joinerDiscoveryFailedNoBeacon"); 01953 return; 01954 } 01955 01956 thread_network_select(cur_interface, device_configuration_ptr, discover_response); 01957 01958 if (!ns_list_count(discover_response)) { 01959 tr_debug("NO network available for scan"); 01960 thci_trace("joinerDiscoveryFailedNoBeacon"); 01961 goto exit_failure; 01962 } 01963 01964 cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN; 01965 cur_interface->bootsrap_state_machine_cnt = 1; 01966 return; 01967 01968 01969 01970 exit_failure: 01971 01972 thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 01973 } 01974 01975 static void thread_bootstrap_create_unsecure_link_to_parent(protocol_interface_info_entry_t *interface, discovery_response_list_t *nwk_info) 01976 { 01977 mlme_start_t start_req; 01978 memset(&start_req, 0, sizeof(mlme_start_t)); 01979 01980 mac_helper_coordinator_address_set(interface, ADDR_802_15_4_LONG , nwk_info->extented_mac); 01981 01982 interface->mac_parameters->pan_id = nwk_info->pan_id; 01983 interface->mac_parameters->mac_channel = nwk_info->channel; 01984 01985 start_req.PANId = nwk_info->pan_id; 01986 start_req.LogicalChannel = nwk_info->channel; 01987 start_req.ChannelPage = 0; 01988 start_req.BeaconOrder = 0x0f; 01989 start_req.SuperframeOrder = 0x0f; 01990 //SET Beacon Payload 01991 mac_helper_beacon_payload_reallocate(interface, 0); 01992 interface->mac_api->mlme_req(interface->mac_api, MLME_START, (void *)&start_req); 01993 mac_data_poll_init(interface); 01994 mac_helper_mac16_address_set(interface, 0xffff); 01995 tr_debug("Mac Ready"); 01996 } 01997 01998 void thread_discover_native_commissioner_response(protocol_interface_info_entry_t *interface, thread_nwk_discovery_response_list_t *nwk_info) 01999 { 02000 thread_commissioning_link_configuration_s *config_ptr; 02001 int n = 0; 02002 if (ns_list_count(nwk_info) == 0) { 02003 tr_debug("Thread discover:No nwk"); 02004 goto exit_failure; 02005 } 02006 02007 // create list of available networks for native commissioner interface 02008 config_ptr = ns_dyn_mem_alloc(sizeof(thread_commissioning_link_configuration_s) * ns_list_count(nwk_info)); 02009 if (!config_ptr) { 02010 tr_debug("Mac scan confirm:out of resources"); 02011 goto exit_failure; 02012 } 02013 02014 ns_list_foreach(discovery_response_list_t, cur_class, nwk_info) { 02015 config_ptr[n].panId = cur_class->pan_id; 02016 config_ptr[n].Protocol_id = THREAD_PROTOCOL_ID; 02017 config_ptr[n].version = THREAD_PROTOCOL_VERSION; 02018 config_ptr[n].rfChannel = cur_class->channel; 02019 memcpy(config_ptr[n].name, cur_class->network_name, 16); 02020 memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8); 02021 memcpy(config_ptr[n].destination_address, ADDR_LINK_LOCAL_PREFIX, 8); 02022 memcpy(&config_ptr[n].destination_address[8], cur_class->extented_mac, 8); 02023 config_ptr[n].destination_address[8] ^= 2; 02024 config_ptr[n].destination_port = cur_class->commissioner_port; 02025 n++; 02026 } 02027 02028 if (interface->thread_info->native_commissioner_cb) { 02029 interface->thread_info->native_commissioner_cb(interface->id, n, config_ptr); 02030 } 02031 ns_dyn_mem_free(config_ptr); 02032 02033 if (!interface->thread_info->native_commissioner_link) { 02034 tr_debug("Mac scan confirm:continue scanning"); 02035 goto exit_failure; 02036 } 02037 //Free if not matching network found 02038 ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) { 02039 if (cur_class->version != THREAD_PROTOCOL_VERSION || 02040 cur_class->pan_id != interface->thread_info->native_commissioner_link->panId || 02041 memcmp(interface->thread_info->native_commissioner_link->name, cur_class->network_name, 16) != 0 || 02042 memcmp(interface->thread_info->native_commissioner_link->extented_pan_id, cur_class->extented_pan_id, 8) != 0) { 02043 02044 ns_list_remove(nwk_info, cur_class); 02045 ns_dyn_mem_free(cur_class); 02046 02047 } 02048 } 02049 02050 if (ns_list_is_empty(nwk_info)) { 02051 tr_debug("Mac scan confirm:no networks available"); 02052 goto exit_failure; 02053 } 02054 //select best parent link 02055 discovery_response_list_t *best = NULL; 02056 02057 ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) { 02058 ns_list_remove(nwk_info, cur_class); 02059 if (!best || (best && best->dbm < cur_class->dbm)) { 02060 if (best) { 02061 ns_dyn_mem_free(cur_class); 02062 } 02063 best = cur_class; 02064 } else { 02065 ns_dyn_mem_free(cur_class); 02066 } 02067 } 02068 02069 // best is always not null, because the not empty check above 02070 /* coverity[FORWARD_NULL] */ 02071 interface->thread_info->native_commissioner_port = best->commissioner_port; 02072 thread_bootstrap_create_unsecure_link_to_parent(interface, best); 02073 ns_dyn_mem_free(best); 02074 02075 /** 02076 * we should stop scanning and saying that the interface is up 02077 */ 02078 tr_debug("Native commissioning interface ready"); 02079 interface->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 02080 interface->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 02081 interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; 02082 interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 02083 02084 interface->thread_info->routerIdRequested = false; 02085 interface->thread_info->networkDataRequested = false; 02086 02087 interface->bootsrap_state_machine_cnt = 10; 02088 02089 clear_power_state(ICMP_ACTIVE); 02090 thread_bootstrap_ready(interface); 02091 return; 02092 02093 02094 02095 exit_failure: 02096 02097 thread_bootstrap_connection_error(interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 02098 } 02099 02100 02101 02102 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info) 02103 { 02104 device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id); 02105 02106 uint8_t parent_ll_addr[16]; 02107 memcpy(parent_ll_addr, ADDR_LINK_LOCAL_PREFIX, 8); 02108 memcpy(parent_ll_addr + 8, nwk_info->extented_mac, 8); 02109 parent_ll_addr[8] ^= 2; 02110 02111 if (!device_configuration_ptr || blacklist_reject(parent_ll_addr)) { 02112 ns_dyn_mem_free(nwk_info); 02113 thci_trace("joinerDiscoveryFailedNoBeacon"); 02114 thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL); 02115 return; 02116 } 02117 02118 uint8_t private_mac[8]; 02119 ns_sha256_nbits(device_configuration_ptr->eui64, 8, private_mac, 64); 02120 private_mac[0] |= 2; //local administered bit is set 02121 02122 tr_debug("joiner mac id : %s", trace_array(private_mac, 8)); 02123 mac_helper_mac64_set(cur_interface, private_mac); 02124 02125 thread_set_link_local_address(cur_interface); // only to generate IID 02126 02127 thread_bootstrap_create_unsecure_link_to_parent(cur_interface, nwk_info); 02128 02129 thci_trace("joinerDiscoverySuccess"); 02130 uint8_t parentLLAddress[16]; 02131 protocol_6lowpan_interface_get_link_local_cordinator_address(cur_interface, parentLLAddress); 02132 tr_debug("Start commission with %s", trace_ipv6(parentLLAddress)); 02133 cur_interface->bootsrap_state_machine_cnt = 0; 02134 02135 if (0 > thread_ccm_commission_start(cur_interface, parentLLAddress, nwk_info, thread_bootstrap_joiner_application_commission_done_cb)) { 02136 thread_joiner_application_pskd_commission_start(cur_interface->id, parentLLAddress, nwk_info->joiner_port, nwk_info->pan_id, nwk_info->extented_pan_id, nwk_info->channel, thread_bootstrap_joiner_application_commission_done_cb); 02137 } 02138 ns_dyn_mem_free(nwk_info); 02139 02140 } 02141 02142 void thread_bootsrap_device_synch_fail(protocol_interface_info_entry_t *cur) 02143 { 02144 tr_debug("Link Synch Fail -->Parent Scan Start"); 02145 thread_bootstrap_clear_neighbor_entries(cur); 02146 thread_network_synch_data_free(cur->id); 02147 thread_delete_ml64_address(cur); 02148 thread_parent_scan(cur); 02149 } 02150 02151 bool thread_device_synch_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 02152 { 02153 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id); 02154 (void)msgId; 02155 if (!interface) { 02156 return false; 02157 } 02158 02159 if (usedAllRetries) { 02160 thread_bootsrap_device_synch_fail(interface); 02161 return false; 02162 } 02163 02164 return true; 02165 } 02166 02167 bool thread_link_request_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 02168 { 02169 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id); 02170 02171 if (!interface) { 02172 return false; 02173 } 02174 02175 if (usedAllRetries) { 02176 uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId); 02177 tr_debug("Link Request timed out, address: %s", trace_ipv6(addr)); 02178 blacklist_update(addr, false); 02179 return false; 02180 } 02181 02182 return true; 02183 } 02184 static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entry_t *cur) 02185 { 02186 uint16_t my_short_address; 02187 uint8_t parent_mac64[8]; 02188 02189 // link sync is allowed only once in bootstrap start and we might get here in other cases also 02190 if (!cur->thread_info->link_sync_allowed) { 02191 return false; 02192 } 02193 cur->thread_info->link_sync_allowed = false; 02194 02195 int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address); 02196 if (link_info_err != THREAD_NVM_FILE_SUCCESS) { 02197 tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err); 02198 return false; 02199 } 02200 link_info_err = thread_nvm_store_link_info_clear(); 02201 if (link_info_err != THREAD_NVM_FILE_SUCCESS) { 02202 tr_warning("thread_nvm_store_link_info_clear returned %d", link_info_err); 02203 } 02204 if (thread_is_router_addr(my_short_address)) { 02205 thread_info(cur)->routerShortAddress = my_short_address; 02206 thread_dynamic_storage_build_mle_table(cur->id); 02207 thread_router_bootstrap_link_synch_start(cur); 02208 return true; 02209 } 02210 if (!thread_parent_data_allocate(cur->thread_info)) { 02211 tr_info("parent alloc failed"); 02212 return false; 02213 } 02214 02215 cur->thread_info->thread_endnode_parent->shortAddress = 0xfffe; 02216 memcpy(cur->thread_info->thread_endnode_parent->mac64, parent_mac64, 8); 02217 thread_endevice_synch_start(cur); 02218 return true; 02219 } 02220 void thread_bootstrap_start_network_discovery(protocol_interface_info_entry_t *cur) 02221 { 02222 thread_discover_reques_t scan_request; 02223 thread_discovery_ready_cb *discover_ready; 02224 cur->nwk_nd_re_scan_count++; 02225 cur->mac_parameters->nwk_scan_params.stack_chan_list = cur->mac_parameters->mac_channel_list; 02226 02227 02228 if (cur->thread_info->native_commissioner_cb) { 02229 tr_debug("native commissioner network scan start"); 02230 02231 discover_ready = thread_discover_native_commissioner_response; 02232 scan_request.joiner_flag = false; 02233 scan_request.native_commisioner = true; 02234 } else { 02235 discovery_response_list_t *thread_network = thread_discovery_network_description_get(cur->id); 02236 if (thread_network) { 02237 thread_bootsrap_network_join_start(cur, thread_network); 02238 return; 02239 } 02240 02241 tr_debug("scan networks for joining application"); 02242 thci_trace("joinerDiscoveryStarted"); 02243 02244 blacklist_params_set( 02245 THREAD_COMM_BLACKLIST_ENTRY_LIFETIME, 02246 THREAD_COMM_BLACKLIST_TIMER_MAX_TIMEOUT, 02247 THREAD_COMM_BLACKLIST_TIMER_TIMEOUT, 02248 THREAD_BLACKLIST_ENTRY_MAX_NBR, 02249 THREAD_BLACKLIST_PURGE_NBR, 02250 THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT); 02251 02252 scan_request.native_commisioner = false; 02253 scan_request.joiner_flag = true; 02254 02255 discover_ready = thread_bootsrap_discovery_ready_cb; 02256 } 02257 02258 scan_request.channel_mask = cur->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0]; 02259 scan_request.filter_tlv_data = NULL; 02260 scan_request.filter_tlv_length = 0; 02261 if (thread_discovery_network_scan(cur, &scan_request, discover_ready) != 0) { 02262 tr_error("Discovery scan start fail"); 02263 } 02264 } 02265 void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur) 02266 { 02267 link_configuration_s *linkConfiguration; 02268 02269 switch (cur->nwk_bootstrap_state) { 02270 case ER_ACTIVE_SCAN: 02271 tr_debug("Thread SM:Active Scan"); 02272 02273 thread_joiner_application_nvm_link_configuration_load(cur->id); 02274 linkConfiguration = thread_joiner_application_get_config(cur->id); 02275 if (!linkConfiguration) { 02276 thread_bootstrap_start_network_discovery(cur); 02277 return; 02278 } 02279 02280 //SET Link by Static configuration 02281 tr_info("thread network attach start"); 02282 if (thread_mle_service_register(cur, thread_joiner_application_random_mac_get(cur->id)) != 0 || 02283 thread_link_configuration_activate(cur, linkConfiguration) != 0) { 02284 tr_error("Network Bootsrap Start Fail"); 02285 bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, cur); 02286 return; 02287 } 02288 if (thread_bootstrap_sync_after_reset_start(cur)) { 02289 // Link syncronisation started 02290 tr_debug("link synchronisation start"); 02291 return; 02292 } 02293 tr_debug("Parent Scan Start"); 02294 thread_parent_scan(cur); 02295 break; 02296 02297 case ER_SCAN: 02298 tr_debug("Thread SM:Start ER Scan"); 02299 cur->nwk_nd_re_scan_count = 0; 02300 thread_network_attach_start(cur); 02301 break; 02302 02303 case ER_MLE_ATTACH_READY: 02304 case ER_MLE_SYNCH: 02305 case ER_MLE_SCAN: 02306 case ER_CHILD_ID_REQ: 02307 tr_debug("Thread SM:Attach Ready"); 02308 break; 02309 02310 case ER_BOOTSRAP_DONE: 02311 tr_debug("Thread SM:Bootstrap Done"); 02312 cur->nwk_nd_re_scan_count = 0; 02313 break; 02314 case ER_BOOTSTRAP_SCAN_FAIL: 02315 tr_debug("Thread SM:Scan Failed"); 02316 nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, cur); 02317 break; 02318 02319 case ER_BOOTSTRAP_LEADER_UP: 02320 tr_debug("Thread SM:Leader Start"); 02321 thread_leader_service_thread_partitition_generate(cur->id, false); 02322 break; 02323 02324 case ER_BOOTSTRAP_NEW_FRAGMENT_START: 02325 tr_debug("Thread SM:Create New fragment"); 02326 thread_leader_service_thread_partitition_generate(cur->id, true); 02327 break; 02328 02329 default: 02330 tr_warn("Thread SM:Invalid state"); 02331 02332 } 02333 } 02334 void thread_bootstrap_stop(protocol_interface_info_entry_t *cur) 02335 { 02336 thread_bootstrap_address_registration_deinit(); 02337 thread_anycast_address_policy_update(cur->thread_info, false); 02338 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL); 02339 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); 02340 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); 02341 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL); 02342 thread_leader_service_leader_data_free(cur->thread_info); 02343 thread_bootstrap_all_nodes_multicast_unregister(cur); 02344 thread_data_base_init(cur->thread_info, cur->id); 02345 dhcp_client_delete(cur->id); 02346 thread_nd_service_delete(cur->id); 02347 thread_child_id_request_entry_clean(cur); 02348 thread_registered_mcast_addr_entry_clean(cur); 02349 cur->mesh_callbacks = NULL; 02350 } 02351 02352 void thread_bootstrap_child_update_trig(protocol_interface_info_entry_t *cur) 02353 { 02354 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && cur->thread_info->thread_endnode_parent) { 02355 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 02356 } 02357 } 02358 static void thread_border_router_locator_copy(protocol_interface_info_entry_t *cur, thread_commissioner_t *registered_commissioner, uint8_t *data) 02359 { 02360 memcpy(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 02361 memcpy(®istered_commissioner->border_router_address[8], ADDR_SHORT_ADR_SUFFIC, 6); 02362 memcpy(®istered_commissioner->border_router_address[14], data, 2); 02363 } 02364 /* \return -1 Failed 02365 * 0 OK, data not changed 02366 * 1 OK, data changed */ 02367 static int thread_commission_data_tlv_parse(protocol_interface_info_entry_t *cur, uint8_t type, uint8_t length, uint8_t *data) 02368 { 02369 thread_commissioner_t *registered_commissioner = &cur->thread_info->registered_commissioner; 02370 02371 switch (type) { 02372 // This is set by leader 02373 case THREAD_TLV_COMMISSIONER_SESSION_ID: 02374 if (length != 2) { 02375 return -1; 02376 } 02377 if (registered_commissioner->session_id != common_read_16_bit(data)) { 02378 registered_commissioner->session_id = common_read_16_bit(data); 02379 return 1; 02380 } 02381 break; 02382 02383 case THREAD_TLV_STEERING_DATA: 02384 if (length > 16) { 02385 return -1; 02386 } 02387 if (registered_commissioner->steering_data_len != length || memcmp(registered_commissioner->steering_data, data, length)) { 02388 memcpy(registered_commissioner->steering_data, data, length); 02389 registered_commissioner->steering_data_len = length; 02390 return 1; 02391 } 02392 break; 02393 02394 case THREAD_TLV_BORDER_ROUTER_LOCATOR: 02395 if (length != 2) { 02396 return -1; 02397 } 02398 02399 registered_commissioner->commissioner_valid = true; 02400 if (!registered_commissioner->commissioner_valid || 02401 memcmp(®istered_commissioner->border_router_address[14], data, 2) || 02402 memcmp(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8)) { 02403 thread_border_router_locator_copy(cur, registered_commissioner, data); 02404 return 1; 02405 } 02406 break; 02407 02408 default: 02409 break; 02410 02411 } 02412 return 0; 02413 } 02414 static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cur, thread_prefix_tlv_t *prefixTlv, bool stableData) 02415 { 02416 thread_network_local_data_context_entry_t context; 02417 uint8_t cid; 02418 //check possible context id or current allocated 02419 cid = thread_nd_context_id_allocate(&cur->thread_info->networkDataStorage, &cur->thread_info->localServerDataBase, prefixTlv->Prefix, prefixTlv->PrefixLen); 02420 if (cid == 16) { 02421 return -1; 02422 } 02423 02424 context.cid = cid; 02425 context.compression = true; 02426 context.stableData = stableData; 02427 context.contextPrefixLength = prefixTlv->PrefixLen; 02428 if (lowpan_context_update(&cur->lowpan_contexts, cid, 0xffff, prefixTlv->Prefix, prefixTlv->PrefixLen, stableData) != 0) { 02429 return -1; 02430 } 02431 02432 if (thread_nd_local_list_add_contexts(&cur->thread_info->networkDataStorage, prefixTlv, &context) != 0) { 02433 //Free context if allocation fail 02434 lowpan_context_update(&cur->lowpan_contexts, cid, 0, prefixTlv->Prefix, prefixTlv->PrefixLen, stableData); 02435 return -1; 02436 } 02437 02438 return 0; 02439 } 02440 02441 int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, uint8_t *network_data_ptr, uint16_t network_data_length) 02442 { 02443 int ret_val = 0; 02444 uint8_t addr[16]; 02445 uint8_t *dptr; 02446 uint16_t length, data_length, flags; 02447 uint8_t prefix_bytes_len, subLength, preference; 02448 uint8_t type; 02449 bool stableData; 02450 bool update_data = false; 02451 thread_prefix_tlv_t prefixTlv; 02452 thread_network_local_data_context_entry_t context; 02453 thread_border_router_tlv_entry_t genericService; 02454 thread_network_data_cache_entry_t *networkDataStorage = &cur->thread_info->networkDataStorage; 02455 02456 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 02457 if (!linkConfiguration) { 02458 return -1; 02459 } 02460 02461 data_length = network_data_length; 02462 dptr = network_data_ptr; 02463 tr_debug("Start Parsing TLV one by One"); 02464 while (data_length) { 02465 tr_debug("Main TLV: %s", trace_array(dptr, data_length)); 02466 02467 prefixTlv.Prefix = NULL; 02468 prefixTlv.PrefixLen = 0; 02469 02470 type = *dptr++; 02471 if (type & THREAD_NWK_STABLE_DATA) { 02472 stableData = true; 02473 } else { 02474 stableData = false; 02475 } 02476 02477 type &= THREAD_NWK_DATA_TYPE_MASK; 02478 length = *dptr++; 02479 if ((length + 2) > data_length) { 02480 return -1; 02481 } 02482 02483 //SET Pointer & Length ready for next check 02484 data_length -= (length + 2); 02485 if (!stableData && !cur->thread_info->requestFullNetworkData) { 02486 //Skip unstable data when it not requsted 02487 dptr += length; 02488 } else if (type == THREAD_NWK_DATA_TYPE_PREFIX) { 02489 prefixTlv.domainId = *dptr++; 02490 prefixTlv.PrefixLen = *dptr++; 02491 //Decrement length by prefix length 02492 length -= 2; 02493 prefixTlv.Prefix = dptr; 02494 prefix_bytes_len = prefixBits_to_bytes(prefixTlv.PrefixLen); 02495 02496 if (prefix_bytes_len > length) { 02497 return -1; 02498 } 02499 length -= prefix_bytes_len; 02500 dptr += prefix_bytes_len; 02501 tr_debug("Prefix: %s", trace_ipv6_prefix(prefixTlv.Prefix, prefixTlv.PrefixLen)); 02502 02503 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02504 02505 while (length > 2) { 02506 type = *dptr++; 02507 subLength = *dptr++; 02508 length -= 2; 02509 if (type & THREAD_NWK_STABLE_DATA) { 02510 stableData = true; 02511 } else { 02512 stableData = false; 02513 } 02514 type &= THREAD_NWK_DATA_TYPE_MASK; 02515 02516 tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength)); 02517 02518 if (subLength <= length) { 02519 length -= subLength; 02520 if (type == THREAD_NWK_DATA_TYPE_6LOWPAN_ID) { 02521 while (subLength) { 02522 if (*dptr & THREAD_NWK_CONTEXT_COMPRESS_ENABLED) { 02523 context.compression = true; 02524 } else { 02525 context.compression = false; 02526 } 02527 02528 context.cid = (*dptr++ & 0x0f); 02529 context.contextPrefixLength = *dptr++; 02530 context.stableData = stableData; 02531 subLength -= 2; 02532 02533 if (thread_nd_verify_contex_id_is_free(networkDataStorage, prefixTlv.Prefix, &context) == 0) { 02534 thread_nd_local_list_add_contexts(networkDataStorage, &prefixTlv, &context); 02535 02536 } else { 02537 tr_debug("CID reserved already"); 02538 } 02539 } 02540 } else { 02541 02542 while (subLength) { 02543 genericService.routerID = common_read_16_bit(dptr); 02544 dptr += 2; 02545 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 02546 flags = common_read_16_bit(dptr); 02547 dptr += 2; 02548 subLength -= THREAD_BORDER_ROUTER_TLV_LENGTH; 02549 genericService.Prf = ((flags >> THREAD_PRF_BIT_MOVE) & 3); 02550 } else { 02551 /* HAS_ROUTE */ 02552 preference = *dptr++; 02553 subLength -= THREAD_HAS_ROUTE_TLV_LENGTH; 02554 genericService.Prf = ((preference >> THREAD_HAS_ROUTE_PRF_BIT_MOVE) & 3); 02555 } 02556 02557 genericService.stableData = stableData; 02558 02559 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 02560 genericService.P_configure = ((flags >> THREAD_P_CONFIGURE_BIT_MOVE) & 1); 02561 genericService.P_default_route = ((flags >> THREAD_P_DEF_ROUTE_BIT_MOVE) & 1); 02562 genericService.P_dhcp = ((flags >> THREAD_P_DHCP_BIT_MOVE) & 1); 02563 genericService.P_preferred = ((flags >> THREAD_P_PREFERRED_BIT_MOVE) & 1); 02564 genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1); 02565 genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1); 02566 genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1); 02567 genericService.P_res1 = ((flags >> THREAD_P_ND_RES_BIT_MOVE) & 1); 02568 if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) { 02569 if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) { 02570 if (!genericService.P_slaac) { 02571 //Delete Address by this Entry 02572 tr_debug("Delete SLAAC address because not valid."); 02573 addr_delete_matching(cur, prefixTlv.Prefix, 64, ADDR_SOURCE_SLAAC); 02574 } else { 02575 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 02576 if (e->source == ADDR_SOURCE_SLAAC && 02577 bitsequal(e->address, prefixTlv.Prefix, 64)) { 02578 if (genericService.P_preferred) { 02579 tr_debug("SLAAC address set as preferred."); 02580 } else { 02581 tr_debug("SLAAC address set as NOT preferred."); 02582 } 02583 addr_set_preferred_lifetime(cur, e, genericService.P_preferred ? 0xffffffff : 0); 02584 } 02585 } 02586 } 02587 02588 if (!genericService.P_dhcp) { 02589 //Delete DHCPv6 client 02590 memcpy(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 02591 memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); 02592 common_write_16_bit(genericService.routerID, &addr[14]); 02593 tr_debug("Delete DHCPv6 given address"); 02594 dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); 02595 } 02596 } 02597 02598 02599 //Allocate Context 02600 if (cur->thread_info->leader_private_data) { 02601 if (thread_nd_prefix_context_allocate(cur, &prefixTlv, stableData) != 0) { 02602 //Mark Delete for this setup if context allocate fail 02603 thread_nd_local_list_del_on_mesh_server(networkDataStorage, &prefixTlv, &genericService); 02604 } 02605 } 02606 } 02607 } else if (type == THREAD_NWK_DATA_TYPE_ROUTE) { 02608 if (genericService.routerID < 0xfffe) { 02609 thread_nd_local_list_add_route(networkDataStorage, &prefixTlv, &genericService); 02610 tr_debug("added route"); 02611 } 02612 } 02613 } 02614 } 02615 } else { 02616 tr_debug("SERVER Parse fail"); 02617 break; 02618 } 02619 } 02620 } else { 02621 tr_debug("Malform Prefix sub TLV"); 02622 dptr += length; 02623 } 02624 02625 } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && stableData) { 02626 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02627 tr_debug("Stable Commisssion TLV: %i", length); 02628 // Stable commissioning data has the Timestamps and is not processed here 02629 } else { 02630 tr_debug("Malformed stable Commisssion TLV: %i", length); 02631 } 02632 dptr += length; 02633 02634 } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && !stableData) { 02635 if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) { 02636 int data_changed; 02637 tr_debug("Unstable Commisssion TLV: %i", length); 02638 // in thread 1.1 unstable has only commissioner information 02639 cur->thread_info->registered_commissioner.commissioner_valid = false; 02640 while (length > 2) { 02641 type = *dptr++; 02642 subLength = *dptr++; 02643 length -= 2; 02644 tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength)); 02645 02646 if (subLength <= length) { 02647 length -= subLength; 02648 02649 data_changed = thread_commission_data_tlv_parse(cur, type, subLength, dptr); 02650 if (data_changed < 0) { 02651 tr_debug("Fail"); 02652 } else { 02653 if (data_changed == 1) { 02654 update_data = true; 02655 tr_debug("Changed"); 02656 } else { 02657 tr_debug("OK"); 02658 } 02659 } 02660 dptr += subLength; 02661 } else { 02662 tr_debug("SERVER Parse fail"); 02663 break; 02664 } 02665 } 02666 } else { 02667 tr_debug("Malformed unstable Commisssion TLV: %i", length); 02668 dptr += length; 02669 } 02670 } else if (type == THREAD_NWK_DATA_TYPE_SERVICE_DATA) { 02671 thread_network_data_service_entry_t service_entry; 02672 02673 service_entry.T = (*dptr) >> 7; 02674 service_entry.S_id = (*dptr++) & 0x0f; 02675 service_entry.S_stable = stableData; 02676 02677 if (!service_entry.T) { 02678 service_entry.S_enterprise_number = common_read_32_bit(dptr); 02679 dptr += 4; 02680 length -= 4; 02681 } else { 02682 service_entry.S_enterprise_number = THREAD_ENTERPRISE_NUMBER; 02683 } 02684 02685 service_entry.S_service_data_length = *dptr++; 02686 service_entry.S_service_data = dptr; 02687 dptr += service_entry.S_service_data_length; 02688 02689 tr_debug("Service data: %s, enterprise number: %"PRIu32, trace_array(service_entry.S_service_data, 02690 service_entry.S_service_data_length), service_entry.S_enterprise_number); 02691 02692 length -= 2 + service_entry.S_service_data_length; 02693 02694 while (length > 2) { 02695 type = *dptr++; 02696 subLength = *dptr++; 02697 length -= 2; 02698 02699 if (subLength <= length) { 02700 tr_debug("SubType: %02x, length: %d, data: %s", type, length, trace_array(dptr, subLength)); 02701 02702 length -= subLength; 02703 02704 thread_network_data_service_server_entry_t server = {0}; 02705 02706 if (type & THREAD_NWK_STABLE_DATA) { 02707 server.stable = true; 02708 } 02709 02710 server.router_id = common_read_16_bit(dptr); 02711 subLength -= 2; 02712 dptr += 2; 02713 02714 server.server_data = dptr; 02715 server.server_data_length = subLength; 02716 tr_debug("Router ID: %04x, Server data: %s", server.router_id, trace_array(server.server_data, server.server_data_length)); 02717 02718 thread_nd_local_list_add_service(networkDataStorage, &service_entry, &server); 02719 dptr += subLength; 02720 } else { 02721 tr_debug("Server sub-TLV parse fail!"); 02722 return -1; 02723 } 02724 } 02725 } else { 02726 return -1; 02727 } 02728 } 02729 02730 if (update_data) { 02731 ret_val = 1; 02732 } 02733 return ret_val; 02734 } 02735 02736 int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) 02737 { 02738 //Mark old data to be be freed 02739 thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false); 02740 02741 int retVal = thread_bootstrap_network_data_process(cur, cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len); 02742 02743 if (retVal < 0) { 02744 tr_warn("network data update failed: %s", trace_array(cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len)); 02745 return retVal; 02746 } 02747 02748 // delete marked data 02749 if (thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur)) { 02750 thread_bootstrap_child_update_trig(cur); 02751 } 02752 02753 // Learn the routes and dhcp addresses from prefixes 02754 thread_bootstrap_network_prefixes_process(cur); 02755 //Add new anycast addressess learned from network data. 02756 thread_router_bootstrap_anycast_address_register(cur); 02757 // Update joiner router status 02758 thread_management_server_joiner_router_init(cur->id); 02759 thread_management_server_ccm_service_init(cur->id); 02760 02761 // Update border router relay 02762 thread_bbr_commissioner_proxy_service_update(cur->id); 02763 // update beacons 02764 thread_beacon_create_payload(cur); 02765 02766 // Indicate network data change to other modules 02767 thread_bootstrap_pbbr_network_data_process(cur); 02768 thread_border_router_network_data_update_notify(cur); 02769 thread_bbr_network_data_update_notify(cur); 02770 02771 thread_maintenance_timer_set(cur); 02772 02773 return 0; 02774 } 02775 02776 int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint8_t *network_data_ptr, uint16_t network_data_len) 02777 { 02778 if (!cur || !cur->thread_info || !leader_data || network_data_len > THREAD_MAX_NETWORK_DATA_SIZE) { 02779 tr_warn("Network data saving failed"); 02780 return -1; 02781 } 02782 02783 if (thread_attach_ready(cur) != 0) { 02784 return -2; 02785 } 02786 02787 if (thread_network_data_malformed_check(network_data_ptr, network_data_len) != 0) { 02788 tr_warn("Malformed nw data: %s", trace_array(network_data_ptr, network_data_len)); 02789 return -3; 02790 } 02791 02792 // Do not process the network data until we are synchronized 02793 tr_debug("learn new network data"); 02794 02795 if (thread_info(cur)->thread_leader_data->stableDataVersion != leader_data->stableDataVersion) { 02796 thread_info(cur)->thread_leader_data->stableDataVersion = leader_data->stableDataVersion; 02797 cur->thread_info->networkDataStorage.stableUpdatePushed = true; 02798 } 02799 if (thread_info(cur)->thread_leader_data->dataVersion != leader_data->dataVersion) { 02800 thread_info(cur)->thread_leader_data->dataVersion = leader_data->dataVersion; 02801 cur->thread_info->networkDataStorage.temporaryUpdatePushed = true; 02802 } 02803 if ((network_data_len != cur->thread_info->networkDataStorage.network_data_len || 02804 memcmp(cur->thread_info->networkDataStorage.network_data, network_data_ptr, network_data_len) != 0)) { 02805 // Network data was changed so at least it will be unstable change 02806 cur->thread_info->networkDataStorage.temporaryUpdatePushed = true; 02807 tr_debug("Network data changed; size %d stable:%d, unstable:%d", network_data_len, cur->thread_info->networkDataStorage.stableUpdatePushed, cur->thread_info->networkDataStorage.temporaryUpdatePushed); 02808 memcpy(cur->thread_info->networkDataStorage.network_data, network_data_ptr, network_data_len); 02809 cur->thread_info->networkDataStorage.network_data_len = network_data_len; 02810 } 02811 02812 return 0; 02813 } 02814 02815 void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur) 02816 { 02817 // Route prefix is variable-length, so need to zero pad for ip6tos 02818 uint8_t addr[16]; 02819 bool validToLearnRoutes, validToLearOnMeshRoute; 02820 thread_network_server_data_entry_t *weHostService = NULL; 02821 uint16_t routerId; 02822 tr_debug("Network Data process:"); 02823 routerId = cur->mac_parameters->mac_short_address; 02824 thread_network_data_cache_entry_t *networkData; 02825 networkData = &cur->thread_info->networkDataStorage; 02826 validToLearnRoutes = thread_route_possible_add(cur->thread_info->thread_device_mode); 02827 validToLearOnMeshRoute = thread_on_mesh_route_possible_add(cur->thread_info->thread_device_mode); 02828 02829 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); 02830 02831 ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &networkData->localPrefixList ) { 02832 weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->routeList); 02833 tr_debug("Local ServicePrefix: %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02834 02835 if (!weHostService && validToLearnRoutes) { 02836 ns_list_foreach(thread_network_server_data_entry_t, curRouteItem, &curPrefix->routeList) { 02837 thread_addr_write_mesh_local_16(addr, curRouteItem->routerID, cur->thread_info); 02838 tr_debug("Add new route via: %s", trace_ipv6(addr)); 02839 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curRouteItem->Prf); 02840 } 02841 } 02842 02843 weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->borderRouterList); 02844 if (weHostService) { 02845 tr_debug("I'm Hosting BR"); 02846 } 02847 02848 ns_list_foreach(thread_network_server_data_entry_t, curBorderRouter, &curPrefix->borderRouterList) { 02849 //Set Default route ::/0 02850 if (curBorderRouter->P_default_route) { 02851 if (!(weHostService && weHostService->P_default_route) && validToLearnRoutes) { 02852 thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); 02853 tr_debug("Add default route via: %s", trace_ipv6(addr)); 02854 ipv6_route_add(NULL, 0, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf); 02855 } 02856 } 02857 ipv6_stack_route_advert_update(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, RA_PRF_LOW); 02858 02859 if (thread_nd_on_mesh_address_valid(curBorderRouter)) { 02860 if (validToLearOnMeshRoute) { 02861 if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id, curPrefix->servicesPrefix)) { 02862 // don't add 02863 tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02864 } else if (curBorderRouter->P_res1) { 02865 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, 0xffffffff, 0); 02866 } else { 02867 //add 02868 tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); 02869 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf); 02870 } 02871 } 02872 } 02873 02874 if (curBorderRouter->P_dhcp) { 02875 /* All end device types perform BR RLOC16 -> ALOC16 02876 replacement if stable network data was requested. */ 02877 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST || 02878 cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) && 02879 cur->thread_info->requestFullNetworkData == false) { 02880 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) { 02881 curBorderRouter->routerID = 0xfc00; 02882 curBorderRouter->routerID |= curRoute->cid; 02883 tr_debug("Replaced router ID with ALOC16: %04x", curBorderRouter->routerID); 02884 } 02885 } 02886 02887 if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { 02888 thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); 02889 /* Do not allow multiple DHCP solicits from one prefix => delete previous */ 02890 dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); 02891 if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, thread_dhcp_client_gua_error_cb) == 0) { 02892 tr_debug("GP Address Requested"); 02893 } 02894 } 02895 } else { 02896 /* All end device types perform RLOC16 -> 0xfffe 02897 replacement if stable network data was requested. */ 02898 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST || 02899 cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) && 02900 cur->thread_info->requestFullNetworkData == false) { 02901 tr_debug("Invalidate router ID: %04x", curBorderRouter->routerID); 02902 curBorderRouter->routerID = 0xfffe; 02903 } 02904 } 02905 02906 if (curBorderRouter->P_preferred) { 02907 if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { 02908 icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); 02909 } 02910 } 02911 // generate address based on res1 bit 02912 if (curBorderRouter->P_res1) { 02913 if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { 02914 thread_bootstrap_dua_address_generate(cur, curPrefix->servicesPrefix, 64); 02915 } 02916 } 02917 02918 } // for each borderRouterList 02919 02920 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) { 02921 uint8_t flags; 02922 flags = curRoute->cid; 02923 if (curRoute->compression) { 02924 flags |= 0x10; 02925 } 02926 02927 lowpan_context_update(&cur->lowpan_contexts, flags, 0xFFFF, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, curRoute->stableData); 02928 } 02929 } // for each localPrefixList 02930 } 02931 02932 void thread_bootstrap_network_data_update(protocol_interface_info_entry_t *cur) 02933 { 02934 if (!cur || !cur->thread_info) { 02935 return; 02936 } 02937 02938 if (cur->thread_info->networkDataStorage.stableUpdatePushed) { 02939 tr_debug("Stable Network Data Update"); 02940 } else if (cur->thread_info->networkDataStorage.temporaryUpdatePushed) { 02941 tr_debug("Temporary Network Data Update"); 02942 } else { 02943 // No changes in network data detected so no processing done 02944 return; 02945 } 02946 tr_info("Network data updated"); 02947 thread_bootstrap_network_data_activate(cur); 02948 thread_router_bootstrap_network_data_distribute(cur); 02949 02950 cur->thread_info->networkDataStorage.stableUpdatePushed = false; 02951 cur->thread_info->networkDataStorage.temporaryUpdatePushed = false; 02952 } 02953 02954 void thread_bootstrap_clear_neighbor_entries(protocol_interface_info_entry_t *cur) 02955 { 02956 if (cur == NULL || cur->thread_info == NULL) { 02957 return; 02958 } 02959 02960 // Remove registered entries in the IP neighbor cache 02961 ns_list_foreach_safe(ipv6_neighbour_t, neighbour, &cur->ipv6_neighbour_cache.list) { 02962 if (neighbour->type == IP_NEIGHBOUR_REGISTERED) { 02963 ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour); 02964 } 02965 } 02966 mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur)); 02967 } 02968 02969 void thread_bootstrap_dynamic_configuration_save(protocol_interface_info_entry_t *cur) 02970 { 02971 uint32_t mac_frame_counter; 02972 if (!cur->thread_info) { 02973 return; 02974 } 02975 02976 if (thread_i_am_router(cur)) { 02977 /* Store information of our children to the dynamic storage */ 02978 mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; 02979 ns_list_foreach_safe(mac_neighbor_table_entry_t, entry, mac_table_list) { 02980 if (thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->mac16)) { 02981 thread_dynamic_storage_child_info_store(cur, entry); 02982 } 02983 } 02984 } 02985 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 02986 mac_helper_link_frame_counter_read(cur->id, &mac_frame_counter); 02987 // in error situation this returns 0 !!!! 02988 uint32_t mle_frame_counter = mle_service_security_get_frame_counter(cur->id); 02989 if (linkConfiguration) { 02990 thread_nvm_store_fast_data_check_and_write(mac_frame_counter, mle_frame_counter, linkConfiguration->key_sequence); 02991 } else { 02992 thread_nvm_store_frame_counters_check_and_write(mac_frame_counter, mle_frame_counter); 02993 } 02994 } 02995 02996 bool thread_bootstrap_link_create_check(protocol_interface_info_entry_t *interface, uint16_t short_address) 02997 { 02998 if (interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE || 02999 interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE) { 03000 // MED's never make any links so return false 03001 return false; 03002 } 03003 03004 if (mle_class_free_entry_count_get(interface) < 1) { 03005 // We dont have room for any new links 03006 tr_warn("Link ignore no room for addr:%x", short_address); 03007 return false; 03008 } 03009 // TODO should check that we have enough room left for children 03010 // TODO Need to drop links for bad routers if no room 03011 03012 if (interface->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 03013 //routers always make links 03014 return true; 03015 } 03016 03017 if (thread_is_router_addr(short_address) == false) { 03018 //incoming advertisement is not from router so return false 03019 return false; 03020 } 03021 03022 if (mle_class_active_neigh_counter(interface) < THREAD_REED_AND_END_DEVICE_NEIGHBOR_LINKS + 1) { 03023 return true; 03024 } 03025 03026 return false; 03027 } 03028 03029 bool thread_bootstrap_link_create_allowed(protocol_interface_info_entry_t *interface, uint16_t short_address, const uint8_t *src_addr) 03030 { 03031 #ifndef HAVE_DEBUG 03032 (void) short_address; 03033 #endif 03034 // Add blacklist of routers that newer answer to us 03035 if (mle_service_interface_tx_queue_size(interface->id) > THREAD_MAX_PARALLEL_MLE_LINK_REQUEST) { 03036 // Maximum parallel link requests 03037 tr_warn("Link ignore too many req addr:%x", short_address); 03038 return false; 03039 } 03040 03041 if (blacklist_reject(src_addr)) { 03042 return false; 03043 } 03044 03045 return true; 03046 } 03047 03048 bool thread_bootstrap_should_register_address(protocol_interface_info_entry_t *cur) 03049 { 03050 // If we are a MTD, send requests to register addresses 03051 // Neither REEDs nor FEDs need to register their addresses 03052 uint8_t mode = thread_mode_get_by_interface_ptr(cur); 03053 return (mode & MLE_DEV_MASK) == MLE_RFD_DEV; 03054 } 03055 03056 /** 03057 * Thread 1.2 support 03058 */ 03059 03060 #ifdef HAVE_THREAD_V2 03061 03062 static void thread_bootstrap_mcast_subscrition_change(protocol_interface_info_entry_t *interface) 03063 { 03064 uint8_t *addr; 03065 uint8_t *ptr; 03066 uint8_t addr_len; 03067 uint8_t br_ml_addr[16]; 03068 03069 if (0 != thread_common_primary_bbr_get(interface, br_ml_addr, NULL, NULL, NULL)) { 03070 return; 03071 } 03072 addr = ns_dyn_mem_temporary_alloc(16 * thread_max_mcast_addr + 2); 03073 if (!addr) { 03074 return; 03075 } 03076 // MLR is sent only for primary BBR for now, but this might change 03077 ptr = addr; 03078 addr_len = 0; 03079 *ptr++ = TMFCOP_TLV_IPV6_ADDRESS; 03080 *ptr++ = 0; // Length will be updated later 03081 ns_list_foreach(if_group_entry_t, cur, &interface->ip_groups) { 03082 if (addr_ipv6_multicast_scope(cur->group) < IPV6_SCOPE_ADMIN_LOCAL) { 03083 continue; 03084 } 03085 if (addr_ipv6_equal(cur->group, ADDR_SITE_LOCAL_ALL_ROUTERS)) { 03086 continue; 03087 } 03088 memcpy(ptr, cur->group, 16); 03089 ptr += 16; 03090 addr_len = ptr - addr; 03091 addr[1] = addr_len - 2;// Fill in the length 03092 if (addr_len > 16 * thread_max_mcast_addr) { 03093 // Send first patch 03094 thread_management_client_mlr_req_send(interface->id, br_ml_addr, addr, addr_len); 03095 // Reset the packet to start 03096 ptr = addr; 03097 ptr += 2; 03098 addr_len = 0; 03099 } 03100 } 03101 if (addr_len != 0) { 03102 // Send rest 03103 thread_management_client_mlr_req_send(interface->id, br_ml_addr, addr, addr_len); 03104 } 03105 ns_dyn_mem_free(addr); 03106 } 03107 static int thread_bootstrap_dua_registration_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 03108 { 03109 (void) source_address; 03110 (void) source_port; 03111 03112 uint16_t addr_len; 03113 uint8_t bbr_status; 03114 uint8_t *addr_data_ptr = NULL; 03115 03116 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_client_get_interface_id_by_service_id(service_id)); 03117 03118 if (!cur) { 03119 return -1; 03120 } 03121 03122 if (!response_ptr) { 03123 tr_warn("DUA.resp failed"); 03124 return -2; 03125 } 03126 03127 if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_STATUS, &bbr_status)) { 03128 return 0; 03129 } 03130 03131 addr_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_TARGET_EID, &addr_data_ptr); 03132 03133 if (addr_len < 16) { 03134 tr_warn("Invalid target eid in DUA.rsp cb message"); 03135 return 0; 03136 } 03137 03138 if_address_entry_t *addr_entry = addr_get_entry(cur, addr_data_ptr); 03139 if (addr_entry) { 03140 // Own processing 03141 if (bbr_status == THREAD_ST_DUA_SUCCESS) { 03142 addr_entry->preferred_lifetime = 0xffffffff; 03143 } else if (bbr_status == THREAD_ST_DUA_DUPLICATE) { 03144 cur->dad_failures++; 03145 thread_bootstrap_dua_address_generate(cur, addr_data_ptr, 64); 03146 } else if (bbr_status == THREAD_ST_DUA_INVALID) { 03147 addr_delete(cur, addr_data_ptr); 03148 } else { 03149 addr_entry->preferred_lifetime = 0; 03150 } 03151 return 0; 03152 } 03153 03154 // processing for MTD children 03155 ipv6_neighbour_t *neighbour_entry; 03156 uint16_t nce_short_addr; 03157 uint8_t destination_address[16] = {0}; 03158 03159 if (bbr_status == THREAD_ST_DUA_SUCCESS) { 03160 // registration successful 03161 return 0; 03162 } 03163 03164 neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, addr_data_ptr); 03165 if (!neighbour_entry) { 03166 return 0; 03167 } 03168 03169 nce_short_addr = common_read_16_bit(neighbour_entry->ll_address + 2); 03170 if (!thread_addr_is_child(cur->thread_info->routerShortAddress, nce_short_addr)) { 03171 ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); 03172 return 0; 03173 } 03174 03175 if (bbr_status == THREAD_ST_DUA_DUPLICATE || bbr_status == THREAD_ST_DUA_INVALID) { 03176 // remove invalid or duplicate child entry 03177 ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); 03178 } 03179 03180 thread_addr_write_mesh_local_16(destination_address, nce_short_addr, cur->thread_info); 03181 03182 thread_management_client_addr_ntf_send(cur->id, destination_address, addr_data_ptr, bbr_status); 03183 03184 return 0; 03185 } 03186 03187 static void thread_bootstrap_dua_registration_send(protocol_interface_info_entry_t *cur, const uint8_t address[16], const uint8_t ml_eid[8], const uint8_t dst_addr[16]) 03188 { 03189 03190 tr_debug("domain address registration (DUA.req send)"); 03191 thread_bootstrap_pbbr_update_done(cur); 03192 03193 uint8_t payload[2 + 16 + 2 + 8]; 03194 uint8_t *ptr; 03195 03196 ptr = payload; 03197 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, address); 03198 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_ML_EID, 8, ml_eid); 03199 03200 coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_NONE, 03201 dst_addr, THREAD_MANAGEMENT_PORT, 03202 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, 03203 THREAD_URI_BBR_DOMAIN_ADDRESS_REGISTRATION, COAP_CT_OCTET_STREAM, 03204 payload, ptr - payload, thread_bootstrap_dua_registration_cb); 03205 } 03206 03207 static int thread_bootstrap_pbbr_update_needed(struct protocol_interface_info_entry *cur, uint16_t rloc, uint8_t seq) 03208 { 03209 if (!cur->thread_info->ccm_info) { 03210 return 0; 03211 } 03212 if (cur->thread_info->ccm_info->update_needed || 03213 seq != cur->thread_info->ccm_info->sequence_number || 03214 rloc != cur->thread_info->ccm_info->rloc) { 03215 return 1; 03216 } 03217 return 0; 03218 } 03219 03220 static void thread_bootstrap_pbbr_update_done(struct protocol_interface_info_entry *cur) 03221 { 03222 // Check if network data changed or bbr info and send proactive an if needed 03223 uint8_t addr[16]; 03224 uint8_t sequence_number; 03225 uint32_t delay_timer; 03226 uint32_t br_mlr_timer; 03227 if (!cur->thread_info->ccm_info) { 03228 return; 03229 } 03230 if (0 == thread_common_primary_bbr_get(cur, addr, &sequence_number, &br_mlr_timer, &delay_timer)) { 03231 // BBR updated 03232 cur->thread_info->ccm_info->rloc = common_read_16_bit(&addr[14]); 03233 cur->thread_info->ccm_info->sequence_number = sequence_number; 03234 cur->thread_info->ccm_info->delay_timer = delay_timer; 03235 cur->thread_info->ccm_info->mlr_timer = br_mlr_timer; 03236 cur->thread_info->ccm_info->update_needed = false; 03237 } 03238 } 03239 03240 static void thread_bootstrap_pbbr_network_data_process(struct protocol_interface_info_entry *cur) 03241 { 03242 // Check if network data changed or bbr info and send proactive an if needed 03243 uint8_t addr[16]; 03244 uint8_t sequence_number; 03245 uint32_t delay_timer; 03246 uint32_t mlr_timeout; 03247 03248 if (0 != thread_common_primary_bbr_get(cur, addr, &sequence_number, &mlr_timeout, &delay_timer)) { 03249 // BBR not present 03250 return; 03251 } 03252 if (1 == thread_bootstrap_pbbr_update_needed(cur, common_read_16_bit(&addr[14]), sequence_number)) { 03253 thread_bootstrap_address_registration_timer_set(cur, 1 + randLIB_get_random_in_range(0, delay_timer / 1000), randLIB_get_random_in_range(1, 5)); 03254 } 03255 } 03256 03257 static void thread_bootstrap_address_registration_trigger(protocol_interface_info_entry_t *interface) 03258 { 03259 // Address notification is sent only for DUA address 03260 thread_bootstrap_pbbr_update_done(interface); 03261 // Send notification on behalf of children 03262 ns_list_foreach(ipv6_neighbour_t, n, &interface->ipv6_neighbour_cache.list) { 03263 if (n->type == IP_NEIGHBOUR_REGISTERED && addr_ipv6_scope(n->ip_address, interface) > IPV6_SCOPE_REALM_LOCAL) { 03264 mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(interface), &n->ll_address[2], ADDR_802_15_4_SHORT ); 03265 if (entry) { 03266 thread_bootstrap_address_registration(interface, n->ip_address, entry->mac64 , true, false); 03267 } 03268 } 03269 } 03270 03271 // Send own Address 03272 ns_list_foreach(if_address_entry_t, e, &interface->ip_addresses) { 03273 if (addr_ipv6_scope(e->address, interface) > IPV6_SCOPE_REALM_LOCAL) { 03274 thread_bootstrap_address_registration(interface, e->address, NULL, false, false); 03275 } 03276 } 03277 } 03278 03279 void thread_bootstrap_address_registration_init() 03280 { 03281 enabled = true; 03282 addr_notificastion_timer = THREAD_PROACTIVE_AN_INTERVAL; 03283 mlr_timer = 0; 03284 } 03285 03286 bool thread_bootstrap_address_registration_running() 03287 { 03288 return enabled; 03289 } 03290 03291 void thread_bootstrap_address_registration_deinit() 03292 { 03293 enabled = false; 03294 } 03295 03296 bool thread_bootstrap_is_domain_prefix(protocol_interface_info_entry_t *interface, const uint8_t *addr) 03297 { 03298 uint8_t address[16]; 03299 memcpy(address, addr, 16); 03300 thread_prefix_tlv_t prefixTlv; 03301 prefixTlv.domainId = 0; 03302 prefixTlv.Prefix = address; 03303 prefixTlv.PrefixLen = 64; 03304 thread_network_data_prefix_cache_entry_t *prefix_entry = NULL; 03305 thread_network_data_cache_entry_t *networkDataCache = &interface->thread_info->networkDataStorage; 03306 prefix_entry = thread_prefix_entry_find(&networkDataCache->localPrefixList , &prefixTlv); 03307 if (!prefix_entry) { 03308 return false; 03309 } 03310 ns_list_foreach(thread_network_server_data_entry_t, brEntry, &prefix_entry->borderRouterList) { 03311 if (brEntry->P_res1) { 03312 return true; 03313 } 03314 } 03315 return false; 03316 } 03317 03318 void thread_bootstrap_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len) 03319 { 03320 if_address_entry_t *def_address = NULL; 03321 uint8_t domain_address[16]; 03322 if (thread_info(cur)->version < THREAD_VERSION_1_2) { 03323 return; 03324 } 03325 addr_delete_matching(cur, NULL, 0, ADDR_SOURCE_THREAD_DOMAIN); 03326 memcpy(domain_address, domain_prefix, 8); 03327 def_address = icmpv6_slaac_address_add(cur, domain_address, domain_prefix_len, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); 03328 if (def_address) { 03329 tr_info("Generated domain address 64: %s", trace_ipv6(def_address->address)); 03330 def_address->source = ADDR_SOURCE_THREAD_DOMAIN; 03331 } else { 03332 tr_error("Domain address creation failed"); 03333 } 03334 } 03335 03336 void thread_bootstrap_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected) 03337 { 03338 uint8_t *ml_eid; 03339 uint8_t br_ml_addr[16]; 03340 uint8_t seq; 03341 uint32_t delay_timer; 03342 03343 if (thread_info(interface)->version < THREAD_VERSION_1_2) { 03344 return; 03345 } 03346 03347 if (!thread_bootstrap_is_domain_prefix(interface, addr)) { 03348 return; 03349 } 03350 tr_debug("domain prefix address"); 03351 if (0 != thread_common_primary_bbr_get(interface, br_ml_addr, &seq, &delay_timer, NULL)) { 03352 // No pBBR present 03353 return; 03354 } 03355 tr_info("domain prefix Primary bbr present"); 03356 03357 if (child_mac64) { 03358 mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(interface), child_mac64, ADDR_802_15_4_LONG ); 03359 03360 if (!entry) { 03361 tr_error("No MLE entry."); 03362 return; 03363 } 03364 03365 ml_eid = thread_neighbor_class_get_mleid(&interface->thread_info->neighbor_class, entry->index ); 03366 if (!ml_eid) { 03367 tr_error("No Thread neighbor."); 03368 return; 03369 } 03370 03371 if (duplicate_child_detected) { 03372 uint8_t dest_address[16] = {0}; 03373 thread_addr_write_mesh_local_16(dest_address, entry->mac16 , interface->thread_info); 03374 thread_management_client_addr_ntf_send(interface->id, dest_address, addr, 3); 03375 return; 03376 } 03377 if (!refresh_child_entry) { 03378 // don't send n/dr for existing entry 03379 return; 03380 } 03381 } else { 03382 link_configuration_s *link_config = thread_joiner_application_get_config(interface->id); 03383 03384 if (!link_config) { 03385 tr_error("No link configuration."); 03386 return; 03387 } 03388 ml_eid = thread_joiner_application_ml_eid_get(interface->id); 03389 } 03390 03391 // Register the DUA address 03392 thread_bootstrap_dua_registration_send(interface, addr, ml_eid, br_ml_addr); 03393 03394 return; 03395 } 03396 03397 03398 void thread_bootstrap_address_registration_timer_set(protocol_interface_info_entry_t *interface, uint16_t dua_delay_seconds, uint16_t mlr_refresh_seconds) 03399 { 03400 (void)interface; 03401 if (dua_delay_seconds != 0) { 03402 addr_notificastion_timer = dua_delay_seconds; 03403 } 03404 if (mlr_refresh_seconds != 0) { 03405 mlr_timer = mlr_refresh_seconds; 03406 } 03407 03408 } 03409 void thread_bootstrap_address_registration_timer(protocol_interface_info_entry_t *interface, uint16_t seconds) 03410 { 03411 uint32_t mlr_timeout; 03412 uint32_t delay_timer; 03413 if (!enabled || interface->thread_info->version < THREAD_VERSION_1_2) { 03414 return; 03415 } 03416 if (thread_bootstrap_should_register_address(interface)) { 03417 if (!interface->thread_info->thread_endnode_parent) { 03418 // We dont have parent so skip 03419 return; 03420 } 03421 if (interface->thread_info->thread_endnode_parent->version >= THREAD_VERSION_1_2) { 03422 // Parent supports all features 03423 return; 03424 } 03425 } 03426 03427 if (0 != thread_common_primary_bbr_get(interface, NULL, NULL, &mlr_timeout, &delay_timer)) { 03428 // BBR not present 03429 return; 03430 } 03431 /* Update multicast addresses */ 03432 if (mlr_timer > seconds) { 03433 mlr_timer -= seconds; 03434 } else { 03435 mlr_timer = mlr_timeout - randLIB_get_random_in_range(30, 50); 03436 thread_bootstrap_mcast_subscrition_change(interface); 03437 } 03438 /* Update global scope addresses (children's as well) */ 03439 if (addr_notificastion_timer > seconds) { 03440 addr_notificastion_timer -= seconds; 03441 } else { 03442 addr_notificastion_timer = THREAD_PROACTIVE_AN_INTERVAL + randLIB_get_random_in_range(0, delay_timer / 1000); 03443 thread_bootstrap_address_registration_trigger(interface); 03444 } 03445 03446 } 03447 void thread_bootstrap_child_address_registration_response_process(struct protocol_interface_info_entry *interface) 03448 { 03449 // if we are version 3 and parent is lower we need to send registrations for them 03450 03451 if (interface->thread_info->version < THREAD_VERSION_1_2) { 03452 thread_bootstrap_address_registration_deinit(); 03453 return; 03454 } 03455 if (!interface->thread_info->thread_endnode_parent) { 03456 // We dont have parent return 03457 thread_bootstrap_address_registration_deinit(); 03458 return; 03459 } 03460 if (interface->thread_info->thread_endnode_parent->version >= THREAD_VERSION_1_2) { 03461 //parent supports 1.2 03462 thread_bootstrap_address_registration_deinit(); 03463 return; 03464 } 03465 // We will start address registration timers 03466 if (!thread_bootstrap_address_registration_running()) { 03467 uint32_t dua_delay; 03468 if (0 != thread_common_primary_bbr_get(interface, NULL, NULL, NULL, &dua_delay)) { 03469 dua_delay = randLIB_get_random_in_range(1, 5); 03470 } 03471 thread_bootstrap_address_registration_init(); 03472 thread_bootstrap_address_registration_timer_set(interface, 1 + randLIB_get_random_in_range(0, dua_delay / 1000), randLIB_get_random_in_range(1, 5)); 03473 } 03474 } 03475 03476 03477 #endif 03478 #endif
Generated on Tue Jul 12 2022 13:54:57 by
1.7.2