Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
thread_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 Fri Jul 22 2022 04:54:03 by
 1.7.2
 1.7.2 
    