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, NULL); 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 } 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_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data) 00241 { 00242 if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) { 00243 return true; 00244 } 00245 if (heard_partition_leader_data.weighting == thread_info(cur)->thread_leader_data->weighting && 00246 heard_partition_leader_data.partitionId < thread_info(cur)->thread_leader_data->partitionId) { 00247 return true; 00248 } 00249 return false; 00250 } 00251 00252 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) 00253 { 00254 //Read Leader Data and verify connectivity 00255 // Leader data is mandatory 00256 if (!thread_leader_data_parse(ptr, data_length, leaderData)) { 00257 return false; 00258 } 00259 00260 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) { 00261 return false; 00262 } 00263 00264 if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) { 00265 if (thread_is_router_addr(*shortAddress)) { 00266 //Sender is reeds 00267 return false; 00268 } 00269 routeTlv->dataPtr = NULL; 00270 routeTlv->tlvLen = 0; 00271 } 00272 return true; 00273 } 00274 00275 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) 00276 { 00277 if (!entry_temp) { 00278 return; 00279 } 00280 00281 mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex); 00282 00283 if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) { 00284 mle_entry_timeout_refresh(entry_temp); 00285 } else { 00286 entry_temp->last_contact_time = protocol_core_monotonic_time; 00287 } 00288 00289 if (short_address != entry_temp->short_adr) { 00290 if (thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) { 00291 thread_dynamic_storage_child_info_clear(cur->id, entry_temp); 00292 protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr); 00293 } 00294 entry_temp->short_adr = short_address; 00295 /* throw MLME_GET request, short address is changed automatically in get request callback */ 00296 mlme_get_t get_req; 00297 get_req.attr = macDeviceTable; 00298 get_req.attr_index = entry_temp->attribute_index; 00299 cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req); 00300 } 00301 00302 return; 00303 } 00304 00305 static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address) 00306 { 00307 if ((thread_info(cur)->thread_leader_data->partitionId != leader_data->partitionId) || 00308 (thread_info(cur)->thread_leader_data->weighting != leader_data->weighting)) { 00309 //parent changed partition/weight - reset own routing information 00310 thread_old_partition_data_purge(cur); 00311 } 00312 //check if network data needs to be requested 00313 if (!thread_bootstrap_request_network_data(cur, leader_data, short_address)) { 00314 tr_debug("Parent short address changed - re-attach"); 00315 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00316 return false; 00317 } 00318 00319 return true; 00320 } 00321 00322 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) 00323 { 00324 mle_tlv_info_t routeTlv; 00325 thread_leader_data_t leaderData; 00326 mle_neigh_table_entry_t *entry_temp; 00327 uint16_t shortAddress; 00328 bool adv_from_my_partition; 00329 bool my_parent; 00330 00331 // Check device mode & bootstrap state 00332 if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) || 00333 (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) { 00334 return; 00335 } 00336 00337 tr_debug("Received Advertisement"); 00338 00339 // Validate and parse TLV's 00340 if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) { 00341 return; 00342 } 00343 00344 // Get MLE entry 00345 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL); 00346 00347 // Check if this is from my parent 00348 my_parent = thread_check_is_this_my_parent(cur, entry_temp); 00349 00350 adv_from_my_partition = thread_instance_id_matches(cur, &leaderData); 00351 00352 if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) { 00353 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00354 } 00355 00356 if (entry_temp && !adv_from_my_partition && !my_parent ) { 00357 // Remove MLE entry that are located in other partition and is not my parent 00358 mle_class_remove_entry(cur->id, entry_temp); 00359 entry_temp = NULL; 00360 } 00361 00362 /* Check parent status */ 00363 if (!thread_attach_active_router(cur) && my_parent) { 00364 if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) { 00365 return; 00366 } 00367 } 00368 00369 // Update MLE entry 00370 thread_update_mle_entry(cur, mle_msg, security_headers, entry_temp, shortAddress); 00371 00372 // Process advertisement 00373 if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { 00374 /* REED and FED */ 00375 if (!thread_attach_active_router(cur)) { 00376 /* Check if advertisement is from same partition */ 00377 if (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId ) { 00378 if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) { 00379 // Create link to new neighbor no other processing allowed 00380 thread_link_request_start(cur, mle_msg->packet_src_address); 00381 return; 00382 } 00383 /* Advertisement from higher / lower partition */ 00384 } else { 00385 // Check if better partition is heard 00386 if (thread_bootstrap_partition_process(cur, thread_get_router_count_from_route_tlv(&routeTlv), &leaderData, &routeTlv) > 0) { 00387 tr_debug("Start Merge"); 00388 thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL); 00389 return; 00390 } 00391 00392 // REED advertisement to lower partition to help merge faster 00393 if (thread_heard_lower_partition(cur,leaderData)) { 00394 thread_router_bootstrap_reed_merge_advertisement(cur); 00395 } 00396 } 00397 /* ROUTER */ 00398 } else { 00399 if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) { 00400 return; 00401 } 00402 thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress); 00403 } 00404 } 00405 00406 // Process route TLV 00407 if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) && 00408 (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){ 00409 tr_debug("Update Route TLV %x", entry_temp->short_adr); 00410 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp); 00411 } 00412 } 00413 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) 00414 { 00415 uint32_t llFrameCounter; 00416 uint32_t mleFrameCounter; 00417 uint16_t version, shortAddress; 00418 uint16_t messageId; 00419 uint8_t linkMarginfronNeigh; 00420 mle_neigh_table_entry_t *entry_temp; 00421 bool createNew, new_entry_created; 00422 00423 tr_info("MLE LINK ACCEPT"); 00424 00425 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00426 00427 if (messageId == 0) { 00428 tr_debug("No matching challenge"); 00429 return; 00430 } 00431 00432 if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) { 00433 //Free Response only if it is unicast 00434 mle_service_msg_free(messageId); 00435 } 00436 00437 // TODO: Check missing TLV's 00438 if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) || 00439 (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) || 00440 (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) { 00441 return; 00442 } 00443 00444 /* Call to determine whether or not we should create a new link */ 00445 createNew = thread_bootstrap_link_create_check(cur, shortAddress); 00446 00447 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry_created); 00448 00449 if (!entry_temp) { 00450 thread_link_reject_send(cur, mle_msg->packet_src_address); 00451 return; 00452 } 00453 00454 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00455 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00456 } 00457 00458 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter 00459 if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) { 00460 mleFrameCounter = llFrameCounter; 00461 } 00462 00463 entry_temp->threadNeighbor = true; 00464 entry_temp->short_adr = shortAddress; 00465 entry_temp->mle_frame_counter = mleFrameCounter; 00466 // Set full data as REED needs full data and SED will not make links 00467 entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET; 00468 00469 mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry_created); 00470 00471 if (entry_temp->timeout_rx) { 00472 mle_entry_timeout_refresh(entry_temp); 00473 } else { 00474 mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME); 00475 } 00476 00477 if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) { 00478 // If we both are routers, mark the link as 2-way 00479 entry_temp->handshakeReady = 1; 00480 tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady); 00481 } else { 00482 tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady); 00483 } 00484 00485 blacklist_update(mle_msg->packet_src_address, true); 00486 00487 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) { 00488 thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh); 00489 } 00490 } 00491 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg) 00492 { 00493 uint64_t timestamp; 00494 uint16_t panid; 00495 uint8_t *ptr; 00496 uint8_t channel_page; 00497 uint16_t channel; 00498 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); 00499 00500 00501 tr_info("Recv Dataset Announce"); 00502 if (8 > thread_tmfcop_tlv_data_get_uint64(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_ACTIVE_TIMESTAMP,×tamp)) { 00503 tr_error("Missing timestamp TLV"); 00504 return; 00505 } 00506 if (2 > thread_tmfcop_tlv_data_get_uint16(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_PANID,&panid)) { 00507 tr_error("Missing Panid TLV"); 00508 return; 00509 } 00510 if (3 > thread_tmfcop_tlv_find(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_CHANNEL,&ptr)) { 00511 tr_error("Missing Channel TLV"); 00512 return; 00513 } 00514 channel_page = ptr[0]; 00515 channel = common_read_16_bit(&ptr[1]); 00516 00517 if (linkConfiguration->timestamp == timestamp) { 00518 // We received same timestamp 00519 tr_debug("Same timestamp"); 00520 return; 00521 } 00522 00523 if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timestamp == timestamp){ 00524 // We received same timestamp again 00525 tr_debug("Processing announce with same timestamp"); 00526 return; 00527 } 00528 00529 00530 if (linkConfiguration->timestamp > timestamp) { 00531 // We received older time stamp we just announce back to originator channel 00532 thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, channel); 00533 return; 00534 } 00535 00536 tr_debug("New configuration received"); 00537 thread_bootstrap_temporary_attach(cur,channel_page, channel, panid, timestamp); 00538 } 00539 00540 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) 00541 { 00542 thread_leader_data_t leaderData; 00543 mle_tlv_info_t networkDataTlv; 00544 mle_tlv_info_t ConfigurationTlv; 00545 uint64_t active_timestamp = 0; 00546 uint64_t pending_timestamp = 0;// means no pending timestamp 00547 mle_neigh_table_entry_t *entry_temp; 00548 bool accept_new_data = false; 00549 bool leaderDataReceived; 00550 00551 tr_debug("Data Response"); 00552 00553 if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) { 00554 leaderDataReceived = true; 00555 } else { 00556 leaderDataReceived = false; 00557 } 00558 if (!leaderDataReceived) { 00559 tr_warn("no leader TLV"); 00560 return; 00561 } 00562 00563 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL); 00564 00565 if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER || 00566 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 00567 if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) { 00568 // We are attached as child and just learn new data 00569 if (!thread_check_is_this_my_parent(cur, entry_temp)) { 00570 return; 00571 } 00572 } else { 00573 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00574 // if receiving data response from different partition it is dropped 00575 return; 00576 } 00577 } 00578 } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 00579 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00580 if (!entry_temp) { 00581 tr_debug("Unknown neighbor"); 00582 return; 00583 } 00584 } 00585 00586 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00587 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId; 00588 thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId; 00589 thread_old_partition_data_purge(cur); 00590 accept_new_data = true; 00591 } 00592 00593 //check response is for link metrics query 00594 thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length); 00595 00596 if (cur->thread_info->networkDataRequested) { 00597 tr_debug("Requested network data received"); 00598 cur->thread_info->networkDataRequested = false; 00599 accept_new_data = true; 00600 } 00601 if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) { 00602 tr_debug("Network data updated"); 00603 accept_new_data = true; 00604 } 00605 // update operational datasets 00606 00607 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00608 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00609 thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00610 } 00611 // TODO check if result is true then need to update all configurations 00612 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00613 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00614 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00615 } 00616 // Check if we are now in sync 00617 // if not matching must send data request again 00618 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp 00619 || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00620 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00621 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00622 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00623 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00624 return; 00625 } 00626 //Check Network Data TLV 00627 if (accept_new_data) { 00628 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00629 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00630 thread_bootstrap_network_data_update(cur); 00631 } else { 00632 tr_debug("SET NWK data Request state"); 00633 } 00634 } 00635 00636 // leader has finished synching network data after reset/restart 00637 if (cur->thread_info->leader_synced) { 00638 cur->thread_info->leader_synced = false; 00639 thread_leader_service_network_data_changed(cur, true, true); 00640 } 00641 } 00642 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) 00643 { 00644 uint16_t len = 150 + 64; 00645 uint8_t mode; 00646 uint32_t keySequence; 00647 uint8_t *ptr; 00648 if (!thread_info(cur)) { 00649 return -1; 00650 } 00651 00652 uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE); 00653 00654 if (bufId == 0) { 00655 return -1; 00656 } 00657 00658 tr_debug("MLE Child update response"); 00659 00660 thread_management_get_current_keysequence(cur->id, &keySequence); 00661 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 00662 00663 ptr = mle_service_get_data_pointer(bufId); 00664 00665 mode = thread_mode_get_by_interface_ptr(cur); 00666 00667 //Write Mode Allways 00668 ptr = mle_tlv_write_mode(ptr, mode); 00669 //Set SRC 00670 ptr = mle_general_write_source_address(ptr, cur); 00671 //SET leader data 00672 ptr = thread_leader_data_tlv_write(ptr, cur); 00673 00674 //Set Addresss TLV 00675 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_ADDRESS_REGISTRATION) && 00676 (mode & MLE_FFD_DEV) == 0) { 00677 ptr = thread_address_registration_tlv_write(ptr, cur); 00678 } 00679 00680 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_TIMEOUT)) { 00681 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 00682 } 00683 00684 if (challengeTlv && challengeTlv->tlvLen) { 00685 ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen); 00686 ptr = mle_general_write_link_layer_framecounter(ptr, cur); 00687 //SET MLE Frame Counter 00688 ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id)); 00689 } 00690 00691 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 00692 tr_debug("Buffer overflow at message write"); 00693 } 00694 mle_service_set_msg_destination_address(bufId, dst_address); 00695 mle_service_send_message(bufId); 00696 return 0; 00697 } 00698 00699 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) 00700 { 00701 thread_leader_data_t leaderData; 00702 mle_tlv_info_t networkDataTlv; 00703 mle_tlv_info_t ConfigurationTlv; 00704 mle_tlv_info_t challengeTlv; 00705 mle_tlv_info_t tlv_req; 00706 uint64_t active_timestamp = 0; 00707 uint64_t pending_timestamp = 0;// means no pending timestamp 00708 mle_neigh_table_entry_t *entry_temp; 00709 bool data_request_needed = false; 00710 00711 tr_debug("Child update request"); 00712 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL); 00713 00714 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) || 00715 !entry_temp || 00716 !thread_check_is_this_my_parent(cur, entry_temp)) { 00717 // Dropped if no leader data or not from parent 00718 tr_warn("invalid message"); 00719 return; 00720 } 00721 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00722 mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req); 00723 00724 // Check if partition changed 00725 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) { 00726 thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId; 00727 thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId; 00728 thread_old_partition_data_purge(cur); 00729 } 00730 //Check Network Data TLV 00731 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00732 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00733 thread_bootstrap_network_data_update(cur); 00734 } 00735 00736 if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || 00737 thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { 00738 // version numbers not in sync need to send data request 00739 data_request_needed = true; 00740 } 00741 00742 // update operational datasets 00743 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00744 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00745 thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00746 } 00747 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00748 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00749 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00750 } 00751 // Check if operational datasets are in sync 00752 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp || 00753 thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00754 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00755 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00756 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00757 data_request_needed = true; 00758 } 00759 thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req); 00760 00761 if (data_request_needed) { 00762 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00763 } 00764 } 00765 00766 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) 00767 { 00768 uint8_t mode; 00769 uint32_t timeout; 00770 mle_neigh_table_entry_t *entry_temp; 00771 thread_leader_data_t leaderData = {0}; 00772 uint8_t status; 00773 bool leader_data_received; 00774 00775 if (cur->thread_info->thread_endnode_parent == NULL) { 00776 return; 00777 } 00778 00779 tr_debug("Child Update Response"); 00780 00781 //mle_service_buffer_find 00782 leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData); 00783 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL); 00784 00785 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) && 00786 status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) { 00787 tr_debug("parent has connection error"); 00788 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00789 return; 00790 } 00791 00792 if (!entry_temp) { 00793 tr_debug("Not Neighbor"); 00794 mle_tlv_info_t challengeTlv; 00795 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00796 thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv); 00797 return; 00798 } 00799 00800 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00801 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00802 } else { 00803 tr_debug("Key ID Mode 2 not used; dropped."); 00804 return; 00805 } 00806 00807 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) { 00808 tr_debug("No Mode"); 00809 return; 00810 } 00811 00812 timeout = cur->thread_info->host_link_timeout; 00813 if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) { 00814 entry_temp->holdTime = 90; 00815 tr_debug("Setting child timeout, value=%"PRIu32, timeout); 00816 mle_entry_timeout_update(entry_temp, timeout); 00817 } 00818 00819 tr_debug("Keep-Alive -->Respond from Parent"); 00820 mle_entry_timeout_refresh(entry_temp); 00821 00822 //Save possible new Leader Data 00823 if (leader_data_received) { 00824 thread_save_leader_data(cur, &leaderData); 00825 } 00826 00827 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00828 if (cur->thread_info->childUpdateReqTimer < 1) { 00829 cur->thread_info->childUpdateReqTimer = 0.8 * timeout; 00830 } 00831 } 00832 //This process is ready 00833 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 00834 if (cur->thread_info->thread_endnode_parent->childUpdatePending) { 00835 tr_debug("Child Update Pending"); 00836 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00837 return; 00838 } 00839 00840 mac_data_poll_protocol_poll_mode_decrement(cur); 00841 00842 } 00843 00844 #endif
Generated on Tue Jul 12 2022 12:45:59 by
