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.
Fork of OmniWheels by
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 Fri Jul 22 2022 04:54:02 by
 1.7.2
 1.7.2 
    