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