Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
thread_host_bootstrap.c
00001 /* 00002 * Copyright (c) 2015-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_host_bootstrap.c 00032 * \brief Add short description about this file!!! 00033 * 00034 */ 00035 00036 #include "nsconfig.h" 00037 #ifdef HAVE_THREAD 00038 #include <string.h> 00039 #include <ns_types.h> 00040 #include <nsdynmemLIB.h> 00041 #include "eventOS_event.h" 00042 #include "eventOS_event_timer.h" 00043 #include "shalib.h" 00044 #include "common_functions.h" 00045 #include "NWK_INTERFACE/Include/protocol.h" 00046 #include "net_thread_test.h" 00047 #include "ns_trace.h" 00048 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00049 #include "6LoWPAN/Thread/thread_common.h" 00050 #include "6LoWPAN/Thread/thread_routing.h" 00051 #include "6LoWPAN/Thread/thread_nd.h" 00052 #include "6LoWPAN/Thread/thread_network_synch.h" 00053 #include "6LoWPAN/Thread/thread_bootstrap.h" 00054 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00055 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00056 #include "6LoWPAN/Thread/thread_leader_service.h" 00057 #include "6LoWPAN/Thread/thread_management_internal.h" 00058 #include "6LoWPAN/Thread/thread_network_synch.h" 00059 #include "6LoWPAN/Thread/thread_lowpower_private_api.h" 00060 #include "6LoWPAN/Thread/thread_extension.h" 00061 #include "6LoWPAN/Thread/thread_joiner_application.h" 00062 #include "6LoWPAN/Thread/thread_management_internal.h" 00063 #include "6LoWPAN/Thread/thread_management_client.h" 00064 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00065 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00066 #include "thread_management_if.h" 00067 #include "Common_Protocols/ipv6.h" 00068 #include "MPL/mpl.h" 00069 #include "MLE/mle_tlv.h" 00070 #include "thread_config.h" 00071 #include "Service_Libs/mle_service/mle_service_api.h" 00072 #include "Service_Libs/blacklist/blacklist.h" 00073 #include "6LoWPAN/MAC/mac_helper.h" 00074 #include "6LoWPAN/MAC/mac_data_poll.h" 00075 #include "Core/include/address.h" 00076 00077 #define TRACE_GROUP "tebs" 00078 00079 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties); 00080 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries); 00081 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries); 00082 00083 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers); 00084 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers); 00085 00086 static int thread_parent_request_build(protocol_interface_info_entry_t *cur); 00087 00088 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur); 00089 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader); 00090 00091 static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr); 00092 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur); 00093 00094 00095 void thread_child_set_default_route(protocol_interface_info_entry_t *cur) 00096 { 00097 thread_parent_info_t *parent = cur->thread_info->thread_endnode_parent; 00098 00099 if (!parent) { 00100 tr_debug("child default route set fail"); 00101 return; 00102 } 00103 cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; 00104 uint8_t ula[16]; 00105 // SET Default route to ::/0 00106 memcpy(ula, ADDR_LINK_LOCAL_PREFIX, 8); 00107 memcpy(&ula[8], parent->mac64 , 8); 00108 ula[8] ^= 2; 00109 if (ipv6_route_add(NULL, 0, cur->id, ula, ROUTE_THREAD, 0xffffffff, 0) == NULL) { 00110 tr_error("fail to add default route"); 00111 } 00112 } 00113 00114 static void thread_network_data_clean(protocol_interface_info_entry_t *cur) 00115 { 00116 tr_debug("Clean network data"); 00117 thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false); 00118 thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur); 00119 } 00120 00121 static void thread_merge_prepare(protocol_interface_info_entry_t *cur) 00122 { 00123 thread_clean_old_16_bit_address_based_addresses(cur); 00124 mpl_clear_realm_scope_seeds(cur); 00125 ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); 00126 ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); 00127 thread_routing_deactivate(&cur->thread_info->routing); 00128 thread_routing_init(&cur->thread_info->routing); 00129 cur->nwk_mode = ARM_NWK_GP_IP_MODE; 00130 thread_network_data_clean(cur); 00131 } 00132 00133 //This function is for Thread Parent scan callback 00134 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 00135 { 00136 protocol_interface_info_entry_t *cur; 00137 00138 cur = protocol_stack_interface_info_get_by_id(interface_id); 00139 if (!cur) { 00140 return false; 00141 } 00142 00143 cur->nwk_nd_re_scan_count++; 00144 00145 tr_debug("Parse parent scan result"); 00146 if (cur->thread_info->thread_attach_scanned_parent) { 00147 uint8_t ll64[16]; 00148 thread_scanned_parent_t *parent = cur->thread_info->thread_attach_scanned_parent; 00149 link_configuration_s *linkConfiguration; 00150 mle_neigh_table_entry_t *entry_temp; 00151 00152 linkConfiguration = thread_joiner_application_get_config(interface_id); 00153 if (!linkConfiguration) { 00154 return false; 00155 } 00156 00157 /* SED requires that scanned parent is added to MLE table */ 00158 memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8); 00159 memcpy(&ll64[8], parent->mac64 , 8); 00160 ll64[8] ^= 2; 00161 00162 entry_temp = mle_class_get_entry_by_ll64(interface_id, parent->linkMarginToParent,ll64, true); 00163 if (entry_temp == NULL) { 00164 return false; 00165 } 00166 entry_temp->threadNeighbor = true; 00167 entry_temp->short_adr = parent->shortAddress; 00168 entry_temp->priorityFlag = true; 00169 entry_temp->holdTime = 90; 00170 entry_temp->mle_frame_counter = parent->mleFrameCounter; 00171 00172 thread_management_key_sets_calc(cur, linkConfiguration, cur->thread_info->thread_attach_scanned_parent->keySequence); 00173 thread_calculate_key_guard_timer(cur, linkConfiguration, true); 00174 00175 mac_helper_devicetable_set(entry_temp, cur, parent->linLayerFrameCounter, mac_helper_default_key_index_get(cur)); 00176 mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME); 00177 00178 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00179 nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 50); 00180 } 00181 00182 tr_debug("Parent found, send child ID req"); 00183 thread_attach_child_id_request_build(cur); 00184 return false; 00185 00186 } else { 00187 uint8_t *dataPtr; 00188 uint16_t dataLength; 00189 00190 if (usedAllRetries) { 00191 if (thread_is_connected(cur)) { 00192 // Did not find any better partition to join. Be happy. 00193 cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY; 00194 return true; 00195 } 00196 // Trig new state which call this 00197 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL); 00198 return false; 00199 } 00200 00201 //GET Data pointer 00202 dataPtr = mle_service_get_payload_start_point(msgId); 00203 dataLength = mle_service_get_payload_length(msgId); 00204 00205 if (dataPtr) { 00206 mle_tlv_info_t tlv_info; 00207 //Scan MLE_TYPE_SCAN_MASK 00208 if (mle_tlv_option_discover(dataPtr, dataLength, MLE_TYPE_SCAN_MASK, &tlv_info)) { 00209 dataPtr = tlv_info.dataPtr; 00210 *dataPtr |= 0x40; //ADD REED Bit 00211 } 00212 } 00213 } 00214 return true; 00215 } 00216 00217 static int thread_parent_request_build(protocol_interface_info_entry_t *cur) 00218 { 00219 uint8_t *ptr; 00220 uint8_t mode; 00221 mle_message_timeout_params_t timeout; 00222 uint32_t keySequence; 00223 uint8_t scanMask = 0x80; 00224 00225 mle_service_interface_tx_queue_clean(cur->id); 00226 00227 uint16_t buf_id = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_PARENT_REQUEST); 00228 if (buf_id == 0) { 00229 return -1; 00230 } 00231 00232 if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH || 00233 cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY || 00234 cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED || 00235 cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 00236 // When doing re-attach End devices are immediately accepted as parents 00237 scanMask |= 0x40; 00238 } 00239 thread_management_get_current_keysequence(cur->id, &keySequence); 00240 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00241 00242 //SET Multicast to all Router ff02::2 00243 mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_ROUTERS); 00244 tr_debug("Thread parent request"); 00245 00246 ptr = mle_service_get_data_pointer(buf_id); 00247 ptr = mle_tlv_write_scan_mask(ptr, scanMask); 00248 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 00249 mode = thread_mode_get_by_interface_ptr(cur); 00250 00251 /* If we are a SLEEPY host, we do NOT set RX_ON_IDLE bit in parent requests */ 00252 /* NOTE: the RX_ON_IDLE is temporarily set on the interface during bootstrap */ 00253 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00254 mode &= ~MLE_RX_ON_IDLE; 00255 } 00256 00257 ptr = mle_tlv_write_mode(ptr, mode); 00258 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 00259 tr_debug("Buffer overflow at message write"); 00260 } 00261 timeout.retrans_max = THREAD_PARENT_REQUEST_MAX_RETRY_CNT; 00262 timeout.timeout_init = 1; 00263 timeout.timeout_max = 2; 00264 timeout.delay = MLE_NO_DELAY; 00265 cur->nwk_nd_re_scan_count = 1; 00266 mle_service_set_packet_callback(buf_id, thread_parent_discover_timeout_cb); 00267 if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) { 00268 mle_service_interface_receiver_handler_update(cur->id, thread_mle_parent_discover_receive_cb); 00269 } else { 00270 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 00271 } 00272 00273 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00274 mle_service_send_message(buf_id); 00275 return 0; 00276 } 00277 00278 void thread_network_attach_start(protocol_interface_info_entry_t *cur) 00279 { 00280 if (thread_parent_request_build(cur) == 0) { 00281 tr_debug("MLE Parent request"); 00282 cur->nwk_bootstrap_state = ER_MLE_SCAN; 00283 cur->bootsrap_state_machine_cnt = 0; 00284 } else { 00285 cur->bootsrap_state_machine_cnt = 5; 00286 } 00287 } 00288 00289 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader) 00290 { 00291 uint8_t shortAddress[2]; 00292 uint8_t status, mode; 00293 uint16_t srcAddress; 00294 uint16_t address16; 00295 uint32_t llFrameCounter; 00296 thread_leader_data_t leaderData; 00297 mle_neigh_table_entry_t *entry_temp; 00298 00299 tr_debug("Validate Link Synch Response"); 00300 //Check First Status 00301 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, ptr, data_length, &status)) { 00302 tr_debug("Synch status response %x",status); 00303 //Clean synch state and start 00304 return -1; 00305 } 00306 // Validate response 00307 // MLE_TYPE_MODE 00308 // Address 00309 // MLE_TYPE_SRC_ADDRESS 00310 // MLE_TYPE_LEADER_DATA 00311 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) || 00312 !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) || 00313 !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) || 00314 !thread_leader_data_parse(ptr, data_length, &leaderData) || 00315 !mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, ptr, data_length, &llFrameCounter)) { 00316 tr_debug("missing TLV's"); 00317 return -1; 00318 } 00319 00320 if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00321 thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource)); 00322 } else { 00323 tr_debug("Key ID Mode 2 not used; dropped."); 00324 return -3; 00325 } 00326 00327 //Update parent link information 00328 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, src_address, true); 00329 00330 if (!entry_temp) { 00331 tr_debug("Neighbor allocate fail"); 00332 return -2; 00333 } 00334 /* 00335 00336 */ 00337 entry_temp->threadNeighbor = true; 00338 entry_temp->short_adr = srcAddress; 00339 entry_temp->handshakeReady = 1; 00340 entry_temp->holdTime = 90; 00341 entry_temp->priorityFlag = true; // Make this our parent 00342 common_write_16_bit(entry_temp->short_adr, shortAddress); 00343 00344 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress); 00345 mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout); 00346 mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, securityHeader->KeyIndex); 00347 00348 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 00349 thread_bootstrap_update_ml16_address(cur, address16); 00350 //SET Parent Info and free scan response info 00351 thread_info(cur)->thread_endnode_parent->shortAddress = srcAddress; 00352 thread_info(cur)->thread_endnode_parent->router_id = srcAddress >> 10; 00353 memcpy(thread_info(cur)->thread_endnode_parent->mac64, entry_temp->mac64, 8); 00354 00355 mle_tlv_info_t routing; 00356 if (mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, &routing)) { 00357 thread_router_bootstrap_route_tlv_push(cur, routing.dataPtr, routing.tlvLen, linkMargin, entry_temp); 00358 } 00359 00360 //Copy Leader Data 00361 *thread_info(cur)->thread_leader_data = leaderData; 00362 00363 /*save the data version to one less than what was received so that any inconsistencies in network data is 00364 * fixed by a data request to parent 00365 */ 00366 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData.stableDataVersion - 1; 00367 thread_info(cur)->thread_leader_data->dataVersion = leaderData.dataVersion - 1; 00368 00369 00370 return 0; 00371 00372 } 00373 00374 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00375 { 00376 tr_debug("Thread MLE message child_synch handler"); 00377 //State machine What packet shuold accept in this case 00378 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00379 if (!cur) { 00380 return; 00381 } 00382 00383 /* Check that message is from link-local scope */ 00384 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00385 return; 00386 } 00387 00388 uint16_t messageId; 00389 uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm); 00390 //State machine What packet shuold accept in this case 00391 switch (mle_msg->message_type) { 00392 case MLE_COMMAND_CHILD_UPDATE_RESPONSE: 00393 00394 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00395 00396 if (messageId == 0) { 00397 tr_debug("Not for me"); 00398 return; 00399 } 00400 00401 if (thread_end_device_synch_response_validate(cur, mle_msg->data_ptr, mle_msg->data_length, linkMargin, mle_msg->packet_src_address, security_headers) != 0) { 00402 tr_warn("End device synch failed"); 00403 mle_service_msg_free(messageId); 00404 thread_bootsrap_device_synch_fail(cur); 00405 return; 00406 } 00407 mle_tlv_info_t networkDataTlv; 00408 thread_leader_data_t leaderData; 00409 tr_debug("End device synch Possible"); 00410 00411 cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED; 00412 // read network data, and leader data check. Send data request sent if pending set is not in sync 00413 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv) && 00414 thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) && thread_joiner_application_pending_delay_timer_in_sync(cur->id)) { 00415 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00416 } else { 00417 thread_bootstrap_parent_network_data_request(cur, true); 00418 } 00419 thread_bootstrap_attached_ready(cur); 00420 00421 //SET For sleepy state and mode update 00422 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00423 nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 1); 00424 //TRIG Child Update state 00425 thread_bootstrap_child_update_trig(cur); 00426 } 00427 00428 mle_service_msg_free(messageId); 00429 break; 00430 } 00431 } 00432 00433 static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *cur, thread_scanned_parent_t *scanned_parent, uint16_t version, thread_connectivity_t *connectivity) 00434 { 00435 (void) connectivity; 00436 (void) cur; 00437 00438 if (!thread_extension_version_check(thread_info(cur)->version)) { 00439 return false; 00440 } 00441 00442 if (version < scanned_parent->version) { 00443 tr_debug("prefer existing parent response from %"PRIX16, scanned_parent->shortAddress); 00444 return true; 00445 } 00446 00447 return false; 00448 } 00449 00450 /* MLE callback for parent response messages. 00451 * 00452 * The Parent Response contains these TLVs: 00453 * - Source Address TLV 00454 * - Leader Data TLV 00455 * - Link-layer Frame Counter TLV 00456 * - MLE Frame Counter TLV (optional) 00457 * - Response TLV 00458 * - Challenge TLV 00459 * - Link Margin TLV 00460 * - Connectivity TLV 00461 * - Version TLV 00462 */ 00463 void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00464 { 00465 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00466 if (!cur) { 00467 return; 00468 } 00469 00470 /* Check that message is from link-local scope */ 00471 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00472 return; 00473 } 00474 00475 tr_debug("Thread MLE Parent request response Handler"); 00476 //State machine What packet should accept in this case 00477 switch (mle_msg->message_type) { 00478 case MLE_COMMAND_PARENT_RESPONSE: { 00479 thread_scanned_parent_t *scan_result = NULL; 00480 uint16_t messageId; 00481 uint16_t srcAddress, version; 00482 uint32_t llFrameCounter; 00483 uint32_t mleFrameCounter; 00484 uint8_t rssiValue; 00485 mle_tlv_info_t challengeTlv; 00486 uint8_t currentMargin, newMargin; 00487 thread_link_quality_e newLqi; 00488 thread_leader_data_t leaderData; 00489 thread_connectivity_t connectivityTlv; 00490 bool accept_response; 00491 00492 tr_info("Parent Response"); 00493 if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) { 00494 tr_debug("Wrong key mode %u ", security_headers->KeyIdMode); 00495 return; 00496 } 00497 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00498 00499 if (messageId == 0) { 00500 tr_debug("Not for me"); 00501 return; 00502 } 00503 00504 //Read Leader Data and verify connectivity 00505 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00506 return; 00507 } 00508 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &rssiValue)) { 00509 return; 00510 } 00511 if (!thread_connectivity_tlv_parse(mle_msg->data_ptr, mle_msg->data_length, &connectivityTlv)) { 00512 return; 00513 } 00514 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &srcAddress)) { 00515 return; 00516 } 00517 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) { 00518 return; 00519 } 00520 if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) { 00521 return; 00522 } 00523 if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) { 00524 return; 00525 } 00526 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter 00527 if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter)) { 00528 mleFrameCounter = llFrameCounter; 00529 } 00530 00531 /** 00532 * At THREAD_STATE_REATTACH state only accept same Partition ID and Higher ID than current 00533 */ 00534 if (thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH || thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH_RETRY) { 00535 tr_debug("Reattach"); 00536 if (thread_info(cur)->thread_leader_data) { 00537 if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) || 00538 (thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) { 00539 //accept only same ID at reattach phase 00540 return; 00541 } 00542 //Compare ID - when downgrading, accept all 00543 if (!thread_info(cur)->releaseRouterId) { 00544 if (!common_serial_number_greater_8(connectivityTlv.idSequence, thread_info(cur)->routing.router_id_sequence)) { 00545 tr_debug("Drop old partition by old ID"); 00546 return; 00547 } else { 00548 tr_debug("Accept old partition by new ID"); 00549 } 00550 } 00551 } 00552 } else if (thread_info(cur)->thread_attached_state == THREAD_STATE_ATTACH_ANY || 00553 thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED || 00554 thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { 00555 if (thread_info(cur)->thread_leader_data) { 00556 if ((thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) && 00557 (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting)) { 00558 //accept only different ID at anyattach phase 00559 tr_debug("Drop old partition"); 00560 return; 00561 } 00562 } else { 00563 //TODO Fix this 00564 tr_error("No leader Data allocated for AnyAttach,Why?"); 00565 } 00566 } 00567 00568 if (blacklist_reject(mle_msg->packet_src_address)) { 00569 tr_debug("Drop Parent Response because blacklisted"); 00570 return; 00571 } 00572 00573 /* Calculate this parent link margin */ 00574 newMargin = thread_calculate_link_margin(mle_msg->dbm, rssiValue); 00575 newLqi = thread_link_margin_to_quality(newMargin << THREAD_LINK_MARGIN_SCALING); 00576 tr_debug("Parent scan count %d addr:%04x Margin:%d lqi:%d", cur->nwk_nd_re_scan_count, srcAddress, newMargin, newLqi); 00577 if (newLqi == QUALITY_BAD) { 00578 tr_debug("Drop Bad Link"); 00579 accept_response = false; 00580 } else { 00581 if (cur->nwk_nd_re_scan_count <= 1) { 00582 if (newLqi == QUALITY_20dB) { 00583 accept_response = true; 00584 } else { 00585 tr_debug("Drop first time less than QUALITY_20dB"); 00586 accept_response = false; 00587 } 00588 } else { 00589 accept_response = true; 00590 } 00591 } 00592 00593 if (thread_extension_enabled(cur) && 00594 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER && 00595 leaderData.weighting < thread_info(cur)->partition_weighting) { 00596 // Only applies to extensions and only routers that can form new partitions can ignore lower weight 00597 tr_debug("Drop parent due weighting %d<%d", leaderData.weighting, thread_info(cur)->partition_weighting); 00598 return; 00599 } 00600 00601 if (accept_response) { 00602 if (thread_info(cur)->thread_attach_scanned_parent == NULL) { 00603 thread_info(cur)->thread_attach_scanned_parent = ns_dyn_mem_temporary_alloc(sizeof(thread_scanned_parent_t)); 00604 if (!thread_info(cur)->thread_attach_scanned_parent) { 00605 return; 00606 } 00607 thread_info(cur)->thread_attach_scanned_parent->child_id_request_id = 0; 00608 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00609 tr_debug("Partition %"PRIu32, leaderData.partitionId); 00610 } else { 00611 uint32_t currentPartitionId = thread_info(cur)->thread_attach_scanned_parent->leader_data.partitionId; 00612 uint8_t currentWeighting = thread_info(cur)->thread_attach_scanned_parent->leader_data.weighting; 00613 tr_debug("Current partition %"PRIu32" old:%"PRIu32" weighting %"PRIu8" old:%"PRIu8, 00614 currentPartitionId, leaderData.partitionId, currentWeighting, leaderData.weighting); 00615 00616 if ((leaderData.partitionId != currentPartitionId) || 00617 (leaderData.weighting != currentWeighting)) { 00618 int retVal = thread_bootstrap_partition_process(cur, connectivityTlv.activeRouters, &leaderData,NULL); 00619 if (retVal > 0) { 00620 // New partition is Higher 00621 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00622 } 00623 } 00624 else if (leaderData.partitionId == currentPartitionId) { 00625 thread_link_quality_e currentLqi; 00626 //Calculate Current summed LQI 00627 scan_result = thread_info(cur)->thread_attach_scanned_parent; 00628 currentMargin = thread_parent_margin_calc(scan_result->linkMarginFromParent, scan_result->linkMarginToParent); 00629 currentLqi = thread_link_margin_to_quality(currentMargin << THREAD_LINK_MARGIN_SCALING); 00630 tr_debug("Compare LQI from margins:"); 00631 tr_debug("New Margin %d vs Cur %d", newMargin, currentMargin); 00632 tr_debug("New Lqi %d vs Cur %d", newLqi, currentLqi); 00633 if (newLqi > currentLqi) { 00634 /*Override old parent data*/ 00635 tr_debug("Better Parent Lqi"); 00636 } else { 00637 if (newLqi == currentLqi) { 00638 //Compare if REED 00639 if (thread_is_router_addr(scan_result->shortAddress) && 00640 !thread_is_router_addr(srcAddress) ) { 00641 scan_result = NULL; 00642 tr_debug("Dropped Response from REED over router"); 00643 } else if (connectivityTlv.parentPriority > scan_result->parentPriority) { 00644 tr_debug("Better parent priority %d>%d", connectivityTlv.parentPriority, scan_result->parentPriority); 00645 } else if (connectivityTlv.parentPriority < scan_result->parentPriority) { 00646 tr_debug("Dropped Response - lower parent priority %d<%d", connectivityTlv.parentPriority, scan_result->parentPriority); 00647 scan_result = NULL; 00648 } else { 00649 tr_debug("Similar LQI check connectivity old: %d,%d,%d new:%d,%d,%d", 00650 scan_result->linkQuality3, scan_result->linkQuality2, scan_result->linkQuality1, 00651 connectivityTlv.linkQuality3, connectivityTlv.linkQuality2, connectivityTlv.linkQuality1); 00652 00653 if (scan_result->linkQuality3 > connectivityTlv.linkQuality3) { 00654 scan_result = NULL; 00655 } 00656 if (scan_result && 00657 scan_result->linkQuality3 == connectivityTlv.linkQuality3 && 00658 scan_result->linkQuality2 > connectivityTlv.linkQuality2) { 00659 scan_result = NULL; 00660 } 00661 if (scan_result && 00662 scan_result->linkQuality3 == connectivityTlv.linkQuality3 && 00663 scan_result->linkQuality2 == connectivityTlv.linkQuality2 && 00664 scan_result->linkQuality1 > connectivityTlv.linkQuality1) { 00665 scan_result = NULL; 00666 } 00667 if(!scan_result) { 00668 tr_debug("Dropped Connectivity is not as good"); 00669 } 00670 } 00671 } else { 00672 scan_result = NULL; 00673 } 00674 } 00675 } 00676 if (scan_result && thread_host_prefer_parent_response(cur, scan_result, version, &connectivityTlv)){ 00677 scan_result = NULL; 00678 } 00679 00680 } 00681 } 00682 00683 if (scan_result) { 00684 // save the result 00685 thread_leader_data_t *leader; 00686 scan_result->linkMarginToParent = thread_compute_link_margin(mle_msg->dbm); 00687 scan_result->linkMarginFromParent = rssiValue; 00688 scan_result->linLayerFrameCounter = llFrameCounter; 00689 scan_result->mleFrameCounter = mleFrameCounter; 00690 scan_result->shortAddress = srcAddress; 00691 scan_result->version = version; 00692 memcpy(scan_result->challengeData, challengeTlv.dataPtr, challengeTlv.tlvLen); 00693 scan_result->chal_len = challengeTlv.tlvLen; 00694 //Save MAC address from LL64 00695 memcpy(scan_result->mac64, (mle_msg->packet_src_address + 8), 8); 00696 scan_result->mac64[0] ^= 2; 00697 leader = &scan_result->leader_data; 00698 //Copy Leader Data 00699 *leader = leaderData; 00700 scan_result->routeCostToLeader = connectivityTlv.leaderCost; 00701 scan_result->linkQuality3 = connectivityTlv.linkQuality3; 00702 scan_result->linkQuality2 = connectivityTlv.linkQuality2; 00703 scan_result->linkQuality1 = connectivityTlv.linkQuality1; 00704 scan_result->parentPriority = connectivityTlv.parentPriority; 00705 scan_result->activeRouters = connectivityTlv.activeRouters; 00706 scan_result->security_key_index = security_headers->KeyIndex; 00707 00708 thread_routing_update_link_margin(cur, scan_result->shortAddress, scan_result->linkMarginToParent, scan_result->linkMarginFromParent); 00709 scan_result->keySequence = common_read_32_bit(security_headers->Keysource); 00710 tr_debug("Current %"PRIu32" RX %"PRIu32" Cnt%"PRIu32, scan_result->leader_data.partitionId, leaderData.partitionId, scan_result->linLayerFrameCounter); 00711 } 00712 break; 00713 } 00714 default: 00715 break; 00716 } 00717 00718 } 00719 00720 /* Callback for child ID request. 00721 * 00722 * Child ID Response contains these TLVs: 00723 * - Source Address TLV 00724 * - Leader Data TLV 00725 * - Address16 TLV 00726 * - Network Data TLV (optional) 00727 * - Route64 TLV (optional) 00728 * - Address Registration TLV (optional) 00729 * - Active Operational Dataset TLV (optional) 00730 * - Pending Operational Dataset TLV (optional) 00731 */ 00732 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00733 { 00734 thread_leader_data_t leaderData; 00735 mle_neigh_table_entry_t *entry_temp; 00736 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00737 link_configuration_s *link_configuration; 00738 if (!cur) { 00739 return; 00740 } 00741 link_configuration = thread_joiner_application_get_config(cur->id); 00742 if (!link_configuration) { 00743 return; 00744 } 00745 00746 /* Check that message is from link-local scope */ 00747 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00748 return; 00749 } 00750 00751 tr_debug("Thread MLE Child request response Handler"); 00752 00753 switch (mle_msg->message_type) { 00754 00755 case MLE_COMMAND_CHILD_ID_RESPONSE: { 00756 uint8_t shortAddress[2]; 00757 uint16_t childId; 00758 mle_tlv_info_t routeTlv, addressRegisteredTlv, networkDataTlv; 00759 mle_tlv_info_t ConfigurationTlv; 00760 uint64_t pending_timestamp = 0; 00761 uint64_t active_timestamp; 00762 thread_scanned_parent_t *scan_result = thread_info(cur)->thread_attach_scanned_parent; 00763 00764 tr_info("Received Child ID Response"); 00765 00766 // Clear old data 00767 if (cur->thread_info->releaseRouterId) { 00768 thread_bootstrap_clear_neighbor_entries(cur); 00769 cur->thread_info->localServerDataBase.release_old_address = true; 00770 } 00771 00772 thread_clean_all_routers_from_neighbor_list(cur->id); 00773 thread_leader_service_stop(interface_id); 00774 thread_leader_service_leader_data_free(cur->thread_info); 00775 thread_merge_prepare(cur); 00776 00777 // Create entry for new parent 00778 entry_temp = mle_class_get_entry_by_ll64(cur->id, thread_compute_link_margin(mle_msg->dbm), mle_msg->packet_src_address, true); 00779 if (entry_temp == NULL) { 00780 // todo: what to do here? 00781 return; 00782 } 00783 00784 //Parse mandatory TLV's 00785 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00786 return; 00787 } 00788 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &entry_temp->short_adr)) { 00789 return; 00790 } 00791 00792 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, mle_msg->data_ptr, mle_msg->data_length, &childId)) { 00793 return; 00794 } 00795 00796 //Read Optional TLV's 00797 mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv); 00798 mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv); 00799 mle_tlv_read_tlv(MLE_TYPE_ROUTE, mle_msg->data_ptr, mle_msg->data_length, &routeTlv); 00800 // update operational datasets 00801 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00802 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00803 thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00804 } 00805 // TODO check if result is true then need to update all configurations 00806 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00807 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00808 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00809 } else if (pending_timestamp < thread_joiner_application_pending_config_timestamp_get(cur->id)) { 00810 // parent did not have timestamp but we haver 00811 tr_info("save pending set for leader"); 00812 thread_joiner_application_next_pending_config_save(cur->id); 00813 thread_joiner_application_pending_config_delete(cur->id); 00814 } 00815 00816 *thread_info(cur)->thread_leader_data = leaderData; 00817 00818 thread_parent_info_t *parent = thread_parent_data_allocate(cur->thread_info); 00819 if (!parent) { 00820 tr_debug("Parent allocate fail."); 00821 return; 00822 } 00823 00824 common_write_16_bit(entry_temp->short_adr, shortAddress); 00825 //Update possible reed address by real router address 00826 scan_result->shortAddress = entry_temp->short_adr; 00827 00828 entry_temp->holdTime = 90; 00829 entry_temp->handshakeReady = 1; 00830 entry_temp->priorityFlag = true; 00831 entry_temp->threadNeighbor = true; 00832 00833 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress); 00834 mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout); 00835 mac_helper_devicetable_set(entry_temp, cur, scan_result->linLayerFrameCounter, security_headers->KeyIndex); 00836 00837 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 00838 00839 thread_bootstrap_update_ml16_address(cur, childId); 00840 if (!thread_is_router_addr(thread_info(cur)->routerShortAddress)) { 00841 thread_info(cur)->routerShortAddress = 0xfffe; 00842 } 00843 00844 mle_service_msg_free(scan_result->child_id_request_id); 00845 00846 scan_result->child_id_request_id = 0; 00847 //SET Parent Info and free scan response info 00848 parent->pathCostToLeader = thread_sum_rx_path_cost_and_link_cost(scan_result->linkMarginToParent, scan_result->linkMarginFromParent, scan_result->routeCostToLeader); 00849 parent->shortAddress = scan_result->shortAddress; 00850 parent->router_id = (scan_result->shortAddress >> 10); 00851 memcpy(parent->mac64, scan_result->mac64, 8); 00852 //Check Network Data TLV 00853 if (networkDataTlv.tlvType == MLE_TYPE_NETWORK_DATA) { 00854 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00855 } else { 00856 cur->thread_info->thread_leader_data->dataVersion--; 00857 cur->thread_info->thread_leader_data->stableDataVersion--; 00858 } 00859 00860 blacklist_update(mle_msg->packet_src_address, true); 00861 00862 // 00863 if (routeTlv.tlvType == MLE_TYPE_ROUTE && routeTlv.tlvLen) { 00864 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , thread_compute_link_margin(mle_msg->dbm), entry_temp); 00865 } 00866 thread_bootstrap_attached_ready(cur); 00867 00868 break; 00869 } 00870 default: 00871 tr_debug("Unsupported TLV %d", mle_msg->message_type); 00872 break; 00873 00874 } 00875 } 00876 00877 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur) 00878 { 00879 mle_message_timeout_params_t timeout; 00880 uint32_t keySequence; 00881 uint16_t buf_id = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, true,MLE_COMMAND_CHILD_UPDATE_REQUEST); 00882 if (buf_id == 0) { 00883 return -1; 00884 } 00885 uint8_t tlv_req[3]; 00886 00887 thread_management_get_current_keysequence(cur->id, &keySequence); 00888 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 00889 uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(buf_id); 00890 //Set Parent Address 00891 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 00892 address_ptr += 8; 00893 memcpy(address_ptr, cur->thread_info->thread_endnode_parent->mac64, 8); 00894 *address_ptr ^= 2; 00895 uint8_t *ptr = mle_service_get_data_pointer(buf_id); 00896 //Add mode 00897 ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur)); 00898 ptr = thread_address_registration_tlv_write(ptr, cur); 00899 tlv_req[0] = MLE_TYPE_ADDRESS16; 00900 tlv_req[1] = MLE_TYPE_NETWORK_DATA; 00901 00902 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00903 // REEDs request Route64 as well 00904 tlv_req[2] = MLE_TYPE_ROUTE; 00905 ptr = mle_tlv_req_tlv(ptr, tlv_req, 3); 00906 } else { 00907 ptr = mle_tlv_req_tlv(ptr, tlv_req, 2); 00908 } 00909 00910 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 00911 tr_debug("Buffer overflow at message write"); 00912 } 00913 00914 tr_debug("Send MLE Child Update Request (Child synchronisation)"); 00915 timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; 00916 timeout.timeout_init = 1; 00917 timeout.timeout_max = 3; 00918 timeout.delay = MLE_NO_DELAY; 00919 00920 mle_service_set_packet_callback(buf_id, thread_device_synch_timeout); 00921 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 00922 mle_service_send_message(buf_id); 00923 return 0; 00924 } 00925 00926 void thread_endevice_synch_start(protocol_interface_info_entry_t *cur) 00927 { 00928 if (cur->thread_info->thread_endnode_parent) { 00929 mle_neigh_table_entry_t *entry_temp; 00930 00931 // Add the parent to the MLE neighbor table 00932 entry_temp = mle_class_get_entry_by_mac64(cur->id, 64, cur->thread_info->thread_endnode_parent->mac64, true); 00933 00934 if (entry_temp) { 00935 entry_temp->short_adr = cur->thread_info->thread_endnode_parent->shortAddress; 00936 entry_temp->handshakeReady = 1; 00937 entry_temp->threadNeighbor = true; 00938 00939 // In case we don't get response to sync; use temporary timeout here, 00940 // Child ID Response handler will set correct value later 00941 mle_entry_timeout_update(entry_temp, 20); 00942 00943 // Add the parent to the MAC table (for e.g. secured/fragmented Child Update Response) 00944 mac_helper_devicetable_set(entry_temp, cur, 0, cur->mac_parameters->mac_default_key_index); 00945 } 00946 } 00947 00948 //Send Child Synch 00949 if (thread_end_device_synch_start(cur) == 0) { 00950 //SET Child synch receiver handler 00951 mle_service_interface_receiver_handler_update(cur->id, thread_child_synch_receive_cb); 00952 cur->nwk_bootstrap_state = ER_MLE_SYNCH; 00953 } 00954 } 00955 00956 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries) 00957 { 00958 mle_neigh_table_entry_t *entry_temp; 00959 thread_scanned_parent_t *scanned_parent; 00960 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00961 uint8_t ll64[16]; 00962 00963 (void)msgId; 00964 00965 if (!cur) { 00966 return false; 00967 } 00968 00969 // Not last retry - keep trying 00970 if (!usedAllRetries) { 00971 return true; 00972 } 00973 00974 //Do not release message inside this call MLE service will do that. 00975 cur->thread_info->thread_attach_scanned_parent->child_id_request_id = 0; 00976 00977 uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId); 00978 tr_debug("Child ID Request timed out, address: %s", trace_ipv6(addr)); 00979 00980 blacklist_update(addr, false); 00981 00982 scanned_parent = cur->thread_info->thread_attach_scanned_parent; 00983 00984 /* Used all retries - if we are on any attach state or */ 00985 /* if we don't have route to leader, start any-attach */ 00986 if (thread_info(cur)->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER || 00987 -1 == thread_route_ready_to_leader(cur) || !scanned_parent) { 00988 tr_debug("start any-attach"); 00989 thread_bootstrap_connection_error(interface_id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL); 00990 goto exit; 00991 } 00992 00993 /* Go back to old partition */ 00994 tr_debug("Back to old partition"); 00995 00996 /* If scanned parent is from other partition, delete from MLE table */ 00997 if (scanned_parent->leader_data.partitionId != thread_info(cur)->thread_leader_data->partitionId) { 00998 memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8); 00999 memcpy(&ll64[8], scanned_parent->mac64 , 8); 01000 ll64[8] ^= 2; 01001 01002 entry_temp = mle_class_get_entry_by_ll64(cur->id, scanned_parent->linkMarginToParent, ll64, false); 01003 if (entry_temp) { 01004 mle_class_remove_entry(cur->id, entry_temp); 01005 } 01006 } 01007 01008 if (thread_info(cur)->thread_endnode_parent) { 01009 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , thread_info(cur)->thread_endnode_parent->mac64); 01010 } 01011 if (cur->thread_info->routerShortAddress == 0xfffe || 01012 !thread_is_router_addr(cur->thread_info->routerShortAddress)) { 01013 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED; 01014 } else { 01015 thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER; 01016 } 01017 01018 cur->thread_info->localServerDataBase.release_old_address = false; 01019 cur->thread_info->releaseRouterId = false; 01020 01021 cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE; 01022 mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb); 01023 01024 exit: 01025 ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent); 01026 cur->thread_info->thread_attach_scanned_parent = NULL; 01027 01028 return false; 01029 } 01030 01031 static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr) 01032 { 01033 *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION; 01034 if (ctx) { 01035 *ptr++ = 9; 01036 //Write TLV to list 01037 *ptr++ = (ctx->cid | 0x80); 01038 memcpy(ptr, addressPtr + 8, 8); 01039 ptr += 8; 01040 } else { 01041 *ptr++ = 17; 01042 //Write TLV to list 01043 *ptr++ = 0; 01044 memcpy(ptr, addressPtr, 16); 01045 ptr += 16; 01046 } 01047 return ptr; 01048 } 01049 01050 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur) 01051 { 01052 uint8_t *ptr, *address_ptr; 01053 uint8_t mode; 01054 mle_message_timeout_params_t timeout; 01055 uint32_t keySequence; 01056 uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_CHILD_ID_REQUEST); 01057 if (buf_id == 0) { 01058 return -1; 01059 } 01060 01061 thread_scanned_parent_t *scan_parent = thread_info(cur)->thread_attach_scanned_parent; 01062 01063 //Set ll64 01064 address_ptr = mle_service_get_msg_destination_address_pointer(buf_id); 01065 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 01066 memcpy(address_ptr + 8 , scan_parent->mac64, 8); 01067 address_ptr[8] ^= 2; 01068 01069 thread_management_get_current_keysequence(cur->id, &keySequence); 01070 mle_service_msg_update_security_params(buf_id, 5, 2, keySequence); 01071 01072 lowpan_context_t *ctx; 01073 uint8_t ml64[16]; 01074 uint8_t request_tlv_list[3]; 01075 uint8_t macShort[2]; 01076 uint8_t reqTlvCnt; 01077 mode = thread_mode_get_by_interface_ptr(cur); 01078 common_write_16_bit(scan_parent->shortAddress, macShort); 01079 //SET Coordinator Address 01080 mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , scan_parent->mac64); 01081 01082 ptr = mle_service_get_data_pointer(buf_id); 01083 /* Allocate a new challenge */ 01084 ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur)); 01085 ptr = mle_general_write_link_layer_framecounter(ptr, cur); 01086 //SET MLE Frame Counter 01087 ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id)); 01088 ptr = mle_tlv_write_response(ptr, scan_parent->challengeData, scan_parent->chal_len); 01089 01090 //Add ML-EID 01091 memcpy(ml64, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8); 01092 memcpy(&ml64[8], cur->iid_slaac, 8); 01093 if ((mode & MLE_FFD_DEV) == 0) { 01094 ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, ml64); 01095 if (ctx) { 01096 //Write TLV to list 01097 ptr = thread_single_address_registration_tlv_write(ptr, ctx, ml64); 01098 } 01099 } 01100 reqTlvCnt = 2; 01101 request_tlv_list[0] = MLE_TYPE_NETWORK_DATA; 01102 01103 request_tlv_list[1] = MLE_TYPE_ADDRESS16; 01104 if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 01105 request_tlv_list[2] = MLE_TYPE_ROUTE; 01106 reqTlvCnt = 3; 01107 } 01108 ptr = mle_tlv_req_tlv(ptr, request_tlv_list, reqTlvCnt); 01109 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 01110 //Set Version 01111 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 01112 //add only active timestamp to the child id request 01113 ptr = thread_active_timestamp_write(cur, ptr); 01114 01115 if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) { 01116 tr_debug("Buffer overflow at message write"); 01117 } 01118 timeout.retrans_max = THREAD_CHILD_ID_REQUEST_MAX_RETRY_CNT; 01119 timeout.timeout_init = 1; 01120 timeout.timeout_max = 3; 01121 timeout.delay = MLE_NO_DELAY; 01122 01123 mle_service_set_packet_callback(buf_id, thread_child_id_req_timeout); 01124 mle_service_set_msg_timeout_parameters(buf_id, &timeout); 01125 mle_service_send_message(buf_id); 01126 //Update MLE handler state 01127 mle_service_interface_receiver_handler_update(cur->id, thread_mle_child_request_receive_cb); 01128 cur->nwk_bootstrap_state = ER_CHILD_ID_REQ; 01129 scan_parent->child_id_request_id = buf_id; 01130 return 0; 01131 } 01132 01133 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties) 01134 { 01135 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01136 (void)msgId; 01137 if (!cur || !cur->thread_info->thread_endnode_parent) { 01138 return false; 01139 } 01140 tr_debug("Child Update CB"); 01141 if (cur->thread_info->thread_endnode_parent->childUpdateProcessStatus) { 01142 //This process is ready 01143 cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false; 01144 if (!cur->thread_info->thread_endnode_parent->childUpdatePending) { 01145 01146 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 01147 //Disable Poll 01148 mac_data_poll_protocol_poll_mode_decrement(cur); 01149 tr_debug("Child Update ready"); 01150 } else { 01151 cur->thread_info->thread_endnode_parent->childUpdatePending = false; 01152 tr_debug("Child Update Pending"); 01153 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 01154 } 01155 return false; 01156 } 01157 01158 if (usedAllRerties) { 01159 01160 cur->thread_info->thread_endnode_parent->childUpdatePending = false; 01161 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 01162 cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false; 01163 mac_data_poll_protocol_poll_mode_decrement(cur); 01164 thread_bootstrap_reset_restart(cur->id); 01165 tr_debug("Restart attachment"); 01166 return false; 01167 } 01168 01169 return true; 01170 01171 } 01172 01173 int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur) 01174 { 01175 mle_message_timeout_params_t timeout; 01176 uint8_t mode; 01177 uint32_t keySequence; 01178 01179 if (!cur->thread_info->thread_endnode_parent) { 01180 return -1; 01181 } 01182 01183 tr_debug("Child Update Request"); 01184 01185 mode = thread_mode_get_by_interface_ptr(cur); 01186 01187 //Build packet 01188 01189 uint16_t bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false, MLE_COMMAND_CHILD_UPDATE_REQUEST); 01190 if (bufId == 0) { 01191 return -1; 01192 } 01193 01194 thread_management_get_current_keysequence(cur->id, &keySequence); 01195 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 01196 01197 uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(bufId); 01198 memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8); 01199 memcpy(address_ptr + 8, cur->thread_info->thread_endnode_parent->mac64, 8); 01200 address_ptr[8] ^= 2; 01201 01202 uint8_t *ptr = mle_service_get_data_pointer(bufId); 01203 ptr = mle_tlv_write_mode(ptr, mode); 01204 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 01205 ptr = thread_leader_data_tlv_write(ptr, cur); 01206 01207 //Set Addresss TLV 01208 if ((mode & MLE_FFD_DEV) == 0) { 01209 ptr = thread_address_registration_tlv_write(ptr, cur); 01210 } 01211 01212 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 01213 tr_debug("Buffer overflow at message write"); 01214 } 01215 timeout.retrans_max = 3; 01216 timeout.timeout_init = 1; 01217 timeout.timeout_max = 4; 01218 timeout.delay = MLE_NO_DELAY; 01219 net_host_mode_t macHostMode; 01220 if (mac_data_poll_host_mode_get(cur,&macHostMode) == 0 && macHostMode == NET_HOST_RX_ON_IDLE) { 01221 thread_end_device_mode_set(cur, false); 01222 } 01223 mac_data_poll_init_protocol_poll(cur); 01224 mle_service_set_packet_callback(bufId, thread_child_update_timeout_cb); 01225 mle_service_set_msg_timeout_parameters(bufId, &timeout); 01226 mle_service_send_message(bufId); 01227 return 0; 01228 } 01229 int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge) 01230 { 01231 uint32_t keySequence; 01232 01233 if (!challenge) { 01234 return -2; 01235 } 01236 01237 uint16_t bufId = mle_service_msg_allocate(cur->id, 16 + challenge->tlvLen, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE); 01238 01239 if (bufId == 0) { 01240 return -1; 01241 } 01242 tr_debug("MLE Child negative Response"); 01243 01244 thread_management_get_current_keysequence(cur->id, &keySequence); 01245 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 01246 01247 uint8_t *ptr = mle_service_get_data_pointer(bufId); 01248 01249 *ptr++ = MLE_TYPE_STATUS; 01250 *ptr++ = 1; 01251 *ptr++ = MLE_STATUS_ERROR; 01252 01253 if (challenge->tlvLen) { 01254 //Add response 01255 ptr = mle_tlv_write_response(ptr, challenge->dataPtr, challenge->tlvLen); 01256 } 01257 01258 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 01259 tr_debug("Buffer overflow at message write"); 01260 } 01261 01262 mle_service_set_msg_destination_address(bufId, dstAddress); 01263 mle_service_send_message(bufId); 01264 return 0; 01265 } 01266 01267 01268 #endif 01269
Generated on Tue Jul 12 2022 14:24:51 by
