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