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