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_mle_message_handler.c
00001 /* 00002 * Copyright (c) 2016-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #include "nsconfig.h" 00030 #ifdef HAVE_THREAD 00031 00032 #include "ns_trace.h" 00033 #include "common_functions.h" 00034 #include "NWK_INTERFACE/Include/protocol.h" 00035 #include <nsdynmemLIB.h> 00036 #include "Service_Libs/mle_service/mle_service_api.h" 00037 #include "Service_Libs/blacklist/blacklist.h" 00038 #include "6LoWPAN/Thread/thread_config.h" 00039 #include "6LoWPAN/Thread/thread_common.h" 00040 #include "6LoWPAN/Thread/thread_lowpower_private_api.h" 00041 #include "6LoWPAN/Thread/thread_mle_message_handler.h" 00042 #include "6LoWPAN/Thread/thread_bootstrap.h" 00043 #include "6LoWPAN/Thread/thread_management_internal.h" 00044 #include "6LoWPAN/Thread/thread_joiner_application.h" 00045 #include "6LoWPAN/Thread/thread_leader_service.h" 00046 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00047 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00048 #include "6LoWPAN/Thread/thread_extension.h" 00049 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00050 #include "6LoWPAN/Thread/thread_network_synch.h" 00051 #include "6LoWPAN/MAC/mac_helper.h" 00052 #include "6LoWPAN/MAC/mac_data_poll.h" 00053 #include "MLE/mle.h" 00054 #include "mac_api.h" 00055 #define TRACE_GROUP "thmh" 00056 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64); 00057 static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor); 00058 static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin); 00059 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); 00060 static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin); 00061 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg); 00062 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin); 00063 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin); 00064 static void thread_parse_child_update_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin); 00065 00066 /* Public functions */ 00067 void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00068 { 00069 /* TODO's: 00070 * - Any incoming link configuration or advertisement message, or an incoming update sent to a 00071 * link-local address, whose IP Hop Limit is not 255, may have been forwarded by a Router 00072 * and MUST be discarded. 00073 */ 00074 00075 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00076 00077 if (!cur) { 00078 return; 00079 } 00080 00081 /* Check that message is from link-local scope */ 00082 if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) { 00083 return; 00084 } 00085 00086 uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm); 00087 00088 // Always save lowpower queries 00089 thread_lowpower_process_request(mle_msg); 00090 00091 switch (mle_msg->message_type) { 00092 case MLE_COMMAND_ACCEPT: { 00093 thread_parse_accept(cur, mle_msg, security_headers, linkMargin); 00094 break; 00095 } 00096 00097 case MLE_COMMAND_METRIC_MANAGEMENT_REQUEST: { 00098 thread_lowpower_metrics_management_query_request_process(cur, mle_msg, security_headers, linkMargin); 00099 break; 00100 } 00101 00102 case MLE_COMMAND_REJECT: { 00103 mle_neigh_table_entry_t *entry_temp; 00104 tr_warn("Reject Link"); 00105 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false); 00106 if (entry_temp) { 00107 mle_class_remove_entry(cur->id, entry_temp); 00108 } 00109 break; 00110 } 00111 00112 case MLE_COMMAND_DATASET_ANNOUNCE: { 00113 thread_parse_annoucement(cur, mle_msg); 00114 break; 00115 } 00116 00117 case MLE_COMMAND_ADVERTISEMENT: { 00118 thread_parse_advertisement(cur, mle_msg, security_headers, linkMargin); 00119 break; 00120 } 00121 00122 case MLE_COMMAND_DATA_RESPONSE: { 00123 thread_parse_data_response(cur, mle_msg, linkMargin); 00124 break; 00125 } 00126 00127 case MLE_COMMAND_CHILD_UPDATE_RESPONSE: 00128 { 00129 thread_parse_child_update_response(cur, mle_msg, security_headers, linkMargin); 00130 break; 00131 } 00132 00133 case MLE_COMMAND_PARENT_RESPONSE: { 00134 tr_debug("MLE parent response received"); 00135 thread_mle_parent_discover_receive_cb(interface_id, mle_msg, security_headers); 00136 break; 00137 } 00138 default: 00139 if ((thread_am_host(cur) || thread_am_reed(cur)) && mle_msg->message_type == MLE_COMMAND_CHILD_UPDATE_REQUEST){ 00140 // Thread host and router in REED mode answer the message same way. Routers only process messages from child 00141 thread_host_child_update_request_process(cur, mle_msg, linkMargin); 00142 } else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00143 thread_router_bootstrap_mle_receive_cb(interface_id, mle_msg, security_headers); 00144 } else { 00145 tr_warn("Not supported MLE message for host %d", mle_msg->message_type); 00146 } 00147 } 00148 00149 } 00150 00151 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) 00152 { 00153 if (thread_info(cur)->thread_leader_data) { 00154 bool requestNetworkdata = false; 00155 if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion)) { 00156 requestNetworkdata = true; 00157 00158 } else if (common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) { 00159 requestNetworkdata = true; 00160 } 00161 00162 if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) { 00163 requestNetworkdata = true; 00164 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1; 00165 thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1; 00166 } 00167 00168 thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId; 00169 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId; 00170 thread_info(cur)->thread_leader_data->weighting = leaderData->weighting; 00171 00172 if (requestNetworkdata) { 00173 thread_bootstrap_parent_network_data_request(cur, false); 00174 } else { 00175 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion; 00176 thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion; 00177 } 00178 } 00179 } 00180 00181 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64) 00182 { 00183 mle_message_timeout_params_t timeout; 00184 uint32_t keySequence; 00185 uint16_t bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST); 00186 00187 if (bufId == 0) { 00188 return -1; 00189 } 00190 00191 timeout.retrans_max = 2; 00192 timeout.timeout_init = 2; 00193 timeout.timeout_max = 3; 00194 timeout.delay = MLE_STANDARD_RESPONSE_DELAY; 00195 00196 thread_management_get_current_keysequence(cur->id, &keySequence); 00197 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 00198 00199 uint8_t *ptr = mle_service_get_data_pointer(bufId); 00200 00201 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 00202 ptr = mle_general_write_source_address(ptr, cur); 00203 ptr = thread_leader_data_tlv_write(ptr, cur); 00204 00205 tr_debug("Synch Req"); 00206 00207 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 00208 tr_debug("Buffer overflow at message write"); 00209 } 00210 00211 mle_service_set_packet_callback(bufId, thread_link_request_timeout); 00212 mle_service_set_msg_destination_address(bufId, router_ll64); 00213 mle_service_set_msg_timeout_parameters(bufId, &timeout); 00214 mle_service_send_message(bufId); 00215 return 0; 00216 } 00217 00218 static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor) 00219 { 00220 int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv); 00221 00222 if (leaderDataUpdate == 1) { 00223 if (neighbor && neighbor->handshakeReady == 1) { 00224 // Request network data if we have a 2-way link 00225 tr_debug("Request New Network Data from %s", trace_ipv6(src_address)); 00226 thread_network_data_request_send(cur, src_address, true); 00227 } else { 00228 00229 } 00230 } else if (leaderDataUpdate == 2) { 00231 tr_debug("Start Merge"); 00232 thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL); 00233 return false; 00234 00235 } else if (leaderDataUpdate < 0) { 00236 tr_warn("Leader data failure"); 00237 return false; 00238 } 00239 return true; 00240 } 00241 00242 static bool thread_reed_partitions_merge(protocol_interface_info_entry_t *cur, uint16_t shortAddress, thread_leader_data_t heard_partition_leader_data) 00243 { 00244 if (thread_is_router_addr(shortAddress)) { 00245 return false; 00246 } 00247 if (thread_extension_version_check(thread_info(cur)->version)) { 00248 // lower weighting heard 00249 if (thread_info(cur)->thread_leader_data->weighting > heard_partition_leader_data.weighting) { 00250 return false; 00251 } 00252 // lower/same partition id heard 00253 if (thread_info(cur)->thread_leader_data->weighting == heard_partition_leader_data.weighting && 00254 thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId ) { 00255 return false; 00256 } 00257 } else if (thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId){ 00258 return false; 00259 } 00260 // can merge to a higher weighting/partition id 00261 thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL); 00262 return true; 00263 } 00264 00265 static bool thread_router_advertiment_tlv_analyze(uint8_t *ptr, uint16_t data_length, thread_leader_data_t *leaderData, uint16_t *shortAddress, mle_tlv_info_t *routeTlv) 00266 { 00267 //Read Leader Data and verify connectivity 00268 // Leader data is mandatory 00269 if (!thread_leader_data_parse(ptr, data_length, leaderData)) { 00270 return false; 00271 } 00272 00273 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) { 00274 return false; 00275 } 00276 00277 if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) { 00278 if (thread_is_router_addr(*shortAddress)) { 00279 //Sender is reeds 00280 return false; 00281 } 00282 routeTlv->dataPtr = NULL; 00283 routeTlv->tlvLen = 0; 00284 } 00285 return true; 00286 } 00287 00288 static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mle_neigh_table_entry_t *entry_temp, uint16_t short_address) 00289 { 00290 if (!entry_temp) { 00291 return; 00292 } 00293 00294 mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex); 00295 00296 if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) { 00297 mle_entry_timeout_refresh(entry_temp); 00298 } else { 00299 entry_temp->last_contact_time = protocol_core_monotonic_time; 00300 } 00301 00302 if (short_address != entry_temp->short_adr) { 00303 if (thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) { 00304 thread_dynamic_storage_child_info_clear(cur->id, entry_temp); 00305 protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr); 00306 } 00307 entry_temp->short_adr = short_address; 00308 /* throw MLME_GET request, short address is changed automatically in get request callback */ 00309 mlme_get_t get_req; 00310 get_req.attr = macDeviceTable; 00311 get_req.attr_index = entry_temp->attribute_index; 00312 cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req); 00313 } 00314 00315 return; 00316 } 00317 00318 static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin) 00319 { 00320 mle_tlv_info_t routeTlv; 00321 thread_leader_data_t leaderData; 00322 uint16_t shortAddress; 00323 mle_neigh_table_entry_t *entry_temp; 00324 00325 // Check device mode & bootstrap state 00326 if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) || 00327 (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) { 00328 return; 00329 } 00330 00331 tr_debug("Received Advertisement"); 00332 00333 // Validate and parse TLV's 00334 if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) { 00335 return; 00336 } 00337 00338 // Get MLE entry 00339 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false); 00340 00341 if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) 00342 && (thread_instance_id_matches(cur, &leaderData))) { 00343 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00344 } 00345 00346 // Check parent status 00347 if (!thread_attach_active_router(cur)) { 00348 //processing for non routers 00349 if (thread_check_is_this_my_parent(cur, entry_temp)) { 00350 //advertisement from parent 00351 if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) || 00352 (thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) { 00353 //parent changed partition/weight - reset own routing information 00354 thread_old_partition_data_purge(cur); 00355 } 00356 //check if network data needs to be requested 00357 if (!thread_bootstrap_request_network_data(cur, &leaderData, shortAddress)) { 00358 tr_debug("Parent short address changed - re-attach"); 00359 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00360 return; 00361 } 00362 } 00363 } 00364 00365 // Update MLE entry 00366 thread_update_mle_entry(cur, mle_msg, security_headers, entry_temp, shortAddress); 00367 00368 // Process advertisement 00369 if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { 00370 if (!thread_attach_active_router(cur)) { 00371 // REED and FED 00372 if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) { 00373 if ((thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) && 00374 (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting)) { 00375 // Create link to new neighbor no other processing allowed 00376 thread_link_request_start(cur, mle_msg->packet_src_address); 00377 return; 00378 } 00379 if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp)) { 00380 // better partition found or new network data learn started 00381 return; 00382 } 00383 } 00384 // process REED advertisement from higher partition 00385 if (thread_reed_partitions_merge(cur, shortAddress, leaderData)) { 00386 return; 00387 } 00388 } else { 00389 //Router 00390 if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) { 00391 return; 00392 } 00393 thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress); 00394 } 00395 } 00396 00397 // Process route TLV 00398 if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) && 00399 (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){ 00400 tr_debug("Update Route TLV %x", entry_temp->short_adr); 00401 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp); 00402 } 00403 } 00404 static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin) 00405 { 00406 uint32_t llFrameCounter; 00407 uint32_t mleFrameCounter; 00408 uint16_t version, shortAddress; 00409 uint16_t messageId; 00410 uint8_t linkMarginfronNeigh; 00411 mle_neigh_table_entry_t *entry_temp; 00412 bool createNew; 00413 00414 tr_info("MLE LINK ACCEPT"); 00415 00416 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00417 00418 if (messageId == 0) { 00419 tr_debug("Not for me"); 00420 return; 00421 } 00422 00423 if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) { 00424 //Free Response only if it is unicast 00425 mle_service_msg_free(messageId); 00426 } 00427 00428 // TODO: Check missing TLV's 00429 if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) || 00430 (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) || 00431 (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) { 00432 return; 00433 } 00434 00435 /* Call to determine whether or not we should create a new link */ 00436 createNew = thread_bootstrap_link_create_check(cur, shortAddress); 00437 00438 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew); 00439 00440 if (!entry_temp) { 00441 thread_link_reject_send(cur, mle_msg->packet_src_address); 00442 return; 00443 } 00444 00445 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00446 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00447 } 00448 00449 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter 00450 if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) { 00451 mleFrameCounter = llFrameCounter; 00452 } 00453 00454 entry_temp->threadNeighbor = true; 00455 entry_temp->short_adr = shortAddress; 00456 entry_temp->mle_frame_counter = mleFrameCounter; 00457 // Set full data as REED needs full data and SED will not make links 00458 entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET; 00459 00460 mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex); 00461 00462 if (entry_temp->timeout_rx) { 00463 mle_entry_timeout_refresh(entry_temp); 00464 } else { 00465 mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME); 00466 } 00467 00468 if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) { 00469 // If we both are routers, mark the link as 2-way 00470 entry_temp->handshakeReady = 1; 00471 tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady); 00472 } else { 00473 tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady); 00474 } 00475 00476 blacklist_update(mle_msg->packet_src_address, true); 00477 00478 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) { 00479 thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh); 00480 } 00481 } 00482 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg) 00483 { 00484 uint64_t timestamp; 00485 uint16_t panid; 00486 uint8_t *ptr; 00487 uint8_t channel_page; 00488 uint16_t channel; 00489 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 00490 00491 00492 tr_info("Recv Dataset Announce"); 00493 if (8 > thread_tmfcop_tlv_data_get_uint64(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_ACTIVE_TIMESTAMP,×tamp)) { 00494 tr_error("Missing timestamp TLV"); 00495 return; 00496 } 00497 if (2 > thread_tmfcop_tlv_data_get_uint16(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_PANID,&panid)) { 00498 tr_error("Missing Panid TLV"); 00499 return; 00500 } 00501 if (3 > thread_tmfcop_tlv_find(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_CHANNEL,&ptr)) { 00502 tr_error("Missing Channel TLV"); 00503 return; 00504 } 00505 channel_page = ptr[0]; 00506 channel = common_read_16_bit(&ptr[1]); 00507 00508 if (linkConfiguration->timestamp == timestamp) { 00509 // We received same timestamp 00510 tr_debug("Same timestamp"); 00511 return; 00512 } 00513 00514 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timestamp == timestamp){ 00515 // We received same timestamp again 00516 tr_debug("Processing announce with same timestamp"); 00517 return; 00518 } 00519 00520 00521 if (linkConfiguration->timestamp > timestamp) { 00522 // We received older time stamp we just announce back to originator channel 00523 thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, channel); 00524 return; 00525 } 00526 00527 tr_debug("New configuration received"); 00528 thread_bootstrap_temporary_attach(cur,channel_page, channel, panid, timestamp); 00529 } 00530 00531 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) 00532 { 00533 thread_leader_data_t leaderData; 00534 mle_tlv_info_t networkDataTlv; 00535 mle_tlv_info_t ConfigurationTlv; 00536 uint64_t active_timestamp = 0; 00537 uint64_t pending_timestamp = 0;// means no pending timestamp 00538 mle_neigh_table_entry_t *entry_temp; 00539 bool accept_new_data = false; 00540 bool leaderDataReceived; 00541 00542 tr_debug("Data Response"); 00543 00544 if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00545 leaderDataReceived = true; 00546 } else { 00547 leaderDataReceived = false; 00548 } 00549 if (!leaderDataReceived) { 00550 tr_warn("no leader TLV"); 00551 return; 00552 } 00553 00554 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false); 00555 00556 if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER || 00557 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 00558 if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) { 00559 // We are attached as child and just learn new data 00560 if (!thread_check_is_this_my_parent(cur, entry_temp)) { 00561 return; 00562 } 00563 } else { 00564 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00565 // if receiving data response from different partition it is dropped 00566 return; 00567 } 00568 } 00569 } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 00570 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00571 if (!entry_temp) { 00572 tr_debug("Unknown neighbor"); 00573 return; 00574 } 00575 } 00576 00577 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00578 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId; 00579 thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId; 00580 thread_old_partition_data_purge(cur); 00581 accept_new_data = true; 00582 } 00583 00584 //check response is for link metrics query 00585 thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length); 00586 00587 if (cur->thread_info->networkDataRequested) { 00588 tr_debug("Requested network data received"); 00589 cur->thread_info->networkDataRequested = false; 00590 accept_new_data = true; 00591 } 00592 if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) { 00593 tr_debug("Network data updated"); 00594 accept_new_data = true; 00595 } 00596 // update operational datasets 00597 00598 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00599 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00600 thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00601 } 00602 // TODO check if result is true then need to update all configurations 00603 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00604 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00605 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00606 } 00607 // Check if we are now in sync 00608 // if not matching must send data request again 00609 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp 00610 || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00611 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00612 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00613 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00614 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00615 return; 00616 } 00617 //Check Network Data TLV 00618 if (accept_new_data) { 00619 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00620 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00621 thread_bootstrap_network_data_update(cur); 00622 } else { 00623 tr_debug("SET NWK data Request state"); 00624 } 00625 } 00626 00627 // leader has finished synching network data after reset/restart 00628 if (cur->thread_info->leader_synced) { 00629 cur->thread_info->leader_synced = false; 00630 thread_leader_service_network_data_changed(cur, true, true); 00631 } 00632 } 00633 static int thread_host_child_update_response_send(protocol_interface_info_entry_t *cur, uint8_t *dst_address, mle_tlv_info_t *challengeTlv, mle_tlv_info_t *requestTlv) 00634 { 00635 uint16_t len = 150 + 64; 00636 uint8_t mode; 00637 uint32_t keySequence; 00638 uint8_t *ptr; 00639 if (!thread_info(cur)) { 00640 return -1; 00641 } 00642 00643 uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE); 00644 00645 if (bufId == 0) { 00646 return -1; 00647 } 00648 00649 tr_debug("MLE Child update response"); 00650 00651 thread_management_get_current_keysequence(cur->id, &keySequence); 00652 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 00653 00654 ptr = mle_service_get_data_pointer(bufId); 00655 00656 mode = thread_mode_get_by_interface_ptr(cur); 00657 00658 //Write Mode Allways 00659 ptr = mle_tlv_write_mode(ptr, mode); 00660 //Set SRC 00661 ptr = mle_general_write_source_address(ptr, cur); 00662 //SET leader data 00663 ptr = thread_leader_data_tlv_write(ptr, cur); 00664 00665 //Set Addresss TLV 00666 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_ADDRESS_REGISTRATION) && 00667 (mode & MLE_FFD_DEV) == 0) { 00668 ptr = thread_address_registration_tlv_write(ptr, cur); 00669 } 00670 00671 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_TIMEOUT)) { 00672 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 00673 } 00674 00675 if (challengeTlv && challengeTlv->tlvLen) { 00676 ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen); 00677 ptr = mle_general_write_link_layer_framecounter(ptr, cur); 00678 //SET MLE Frame Counter 00679 ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id)); 00680 } 00681 00682 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 00683 tr_debug("Buffer overflow at message write"); 00684 } 00685 mle_service_set_msg_destination_address(bufId, dst_address); 00686 mle_service_send_message(bufId); 00687 return 0; 00688 } 00689 00690 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) 00691 { 00692 thread_leader_data_t leaderData; 00693 mle_tlv_info_t networkDataTlv; 00694 mle_tlv_info_t ConfigurationTlv; 00695 mle_tlv_info_t challengeTlv; 00696 mle_tlv_info_t tlv_req; 00697 uint64_t active_timestamp = 0; 00698 uint64_t pending_timestamp = 0;// means no pending timestamp 00699 mle_neigh_table_entry_t *entry_temp; 00700 bool data_request_needed = false; 00701 00702 tr_debug("Child update request"); 00703 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false); 00704 00705 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) || 00706 !entry_temp || 00707 !thread_check_is_this_my_parent(cur, entry_temp)) { 00708 // Dropped if no leader data or not from parent 00709 tr_warn("invalid message"); 00710 return; 00711 } 00712 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00713 mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req); 00714 00715 // Check if partition changed 00716 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00717 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId; 00718 thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId; 00719 thread_old_partition_data_purge(cur); 00720 } 00721 //Check Network Data TLV 00722 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00723 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00724 thread_bootstrap_network_data_update(cur); 00725 } 00726 00727 if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || 00728 thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { 00729 // version numbers not in sync need to send data request 00730 data_request_needed = true; 00731 } 00732 00733 // update operational datasets 00734 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00735 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00736 thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00737 } 00738 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00739 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00740 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00741 } 00742 // Check if operational datasets are in sync 00743 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp || 00744 thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00745 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00746 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00747 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00748 data_request_needed = true; 00749 } 00750 thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req); 00751 00752 if (data_request_needed) { 00753 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00754 } 00755 } 00756 00757 static void thread_parse_child_update_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin) 00758 { 00759 uint8_t mode; 00760 uint32_t timeout; 00761 mle_neigh_table_entry_t *entry_temp; 00762 thread_leader_data_t leaderData = {0}; 00763 uint8_t status; 00764 bool leader_data_received; 00765 00766 tr_debug("Child Update Response"); 00767 00768 leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData); 00769 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false); 00770 00771 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) && 00772 status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) { 00773 tr_debug("parent has connection error"); 00774 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00775 return; 00776 } 00777 00778 if (!entry_temp) { 00779 tr_debug("Not Neighbor"); 00780 mle_tlv_info_t challengeTlv; 00781 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00782 thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv); 00783 return; 00784 } 00785 00786 if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) 00787 && (thread_instance_id_matches(cur, &leaderData))) { 00788 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00789 } else { 00790 tr_debug("Key ID Mode 2 not used; dropped."); 00791 return; 00792 } 00793 00794 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) { 00795 tr_debug("No Mode"); 00796 return; 00797 } 00798 00799 if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) { 00800 entry_temp->holdTime = 90; 00801 tr_debug("Setting child timeout, value=%"PRIu32, timeout); 00802 mle_entry_timeout_update(entry_temp, timeout); 00803 thread_info(cur)->thread_endnode_parent->childUpdateProcessStatus = true; 00804 } 00805 tr_debug("Keep-Alive -->Respond from Parent"); 00806 mle_entry_timeout_refresh(entry_temp); 00807 00808 //Save possible new Leader Data 00809 if (leader_data_received) { 00810 thread_save_leader_data(cur, &leaderData); 00811 } 00812 mac_data_poll_protocol_poll_mode_decrement(cur); 00813 } 00814 00815 #endif
Generated on Tue Jul 12 2022 14:24:55 by
