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