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