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