Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
thread_mle_message_handler.c
00001 /* 00002 * Copyright (c) 2016-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #include "nsconfig.h" 00030 #ifdef HAVE_THREAD 00031 00032 #include "ns_trace.h" 00033 #include "string.h" 00034 #include "common_functions.h" 00035 #include "NWK_INTERFACE/Include/protocol.h" 00036 #include <nsdynmemLIB.h> 00037 #include "Service_Libs/mle_service/mle_service_api.h" 00038 #include "Service_Libs/blacklist/blacklist.h" 00039 #include "6LoWPAN/Thread/thread_config.h" 00040 #include "6LoWPAN/Thread/thread_common.h" 00041 #include "6LoWPAN/Thread/thread_lowpower_private_api.h" 00042 #include "6LoWPAN/Thread/thread_neighbor_class.h" 00043 #include "6LoWPAN/Thread/thread_mle_message_handler.h" 00044 #include "6LoWPAN/Thread/thread_bootstrap.h" 00045 #include "6LoWPAN/Thread/thread_management_internal.h" 00046 #include "6LoWPAN/Thread/thread_joiner_application.h" 00047 #include "6LoWPAN/Thread/thread_leader_service.h" 00048 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00049 #include "6LoWPAN/Thread/thread_host_bootstrap.h" 00050 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00051 #include "6LoWPAN/Thread/thread_network_synch.h" 00052 #include "6LoWPAN/Thread/thread_neighbor_class.h" 00053 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00054 #include "6LoWPAN/MAC/mac_helper.h" 00055 #include "6LoWPAN/MAC/mac_data_poll.h" 00056 #include "Common_Protocols/ipv6.h" 00057 #include "MLE/mle.h" 00058 #include "mac_api.h" 00059 #define TRACE_GROUP "thmh" 00060 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64); 00061 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, mac_neighbor_table_entry_t *neighbor); 00062 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); 00063 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); 00064 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); 00065 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg); 00066 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin); 00067 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin); 00068 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); 00069 00070 /* Public functions */ 00071 void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers) 00072 { 00073 /* TODO's: 00074 * - Any incoming link configuration or advertisement message, or an incoming update sent to a 00075 * link-local address, whose IP Hop Limit is not 255, may have been forwarded by a Router 00076 * and MUST be discarded. 00077 */ 00078 00079 protocol_interface_info_entry_t *cur = mle_msg->interface_ptr; 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 mac_neighbor_table_entry_t *entry_temp; 00104 tr_warn("Reject Link"); 00105 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); 00106 if (entry_temp) { 00107 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), 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 thread_parse_child_update_response(cur, mle_msg, security_headers, linkMargin); 00129 break; 00130 } 00131 00132 case MLE_COMMAND_PARENT_RESPONSE: { 00133 tr_debug("MLE parent response received"); 00134 thread_mle_parent_discover_receive_cb(interface_id, mle_msg, security_headers); 00135 break; 00136 } 00137 default: 00138 if ((thread_am_host(cur) || thread_am_reed(cur)) && mle_msg->message_type == MLE_COMMAND_CHILD_UPDATE_REQUEST) { 00139 // Thread host and router in REED mode answer the message same way. Routers only process messages from child 00140 thread_host_child_update_request_process(cur, mle_msg, linkMargin); 00141 } else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00142 thread_router_bootstrap_mle_receive_cb(interface_id, mle_msg, security_headers); 00143 } else { 00144 tr_warn("Not supported MLE message for host %d", mle_msg->message_type); 00145 } 00146 } 00147 00148 } 00149 00150 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) 00151 { 00152 if (thread_info(cur)->thread_leader_data) { 00153 bool requestNetworkdata = false; 00154 if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion)) { 00155 requestNetworkdata = true; 00156 00157 } else if (common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) { 00158 requestNetworkdata = true; 00159 } 00160 00161 if (!thread_partition_match(cur, leaderData)) { 00162 requestNetworkdata = true; 00163 thread_partition_info_update(cur, leaderData); 00164 } 00165 00166 if (requestNetworkdata) { 00167 thread_bootstrap_parent_network_data_request(cur, false); 00168 } else { 00169 thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion; 00170 thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion; 00171 } 00172 } 00173 } 00174 00175 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64) 00176 { 00177 mle_message_timeout_params_t timeout; 00178 uint32_t keySequence; 00179 uint16_t bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST); 00180 00181 if (bufId == 0) { 00182 return -1; 00183 } 00184 00185 timeout.retrans_max = 2; 00186 timeout.timeout_init = 2; 00187 timeout.timeout_max = 3; 00188 timeout.delay = MLE_STANDARD_RESPONSE_DELAY; 00189 00190 thread_management_get_current_keysequence(cur->id, &keySequence); 00191 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 00192 00193 uint8_t *ptr = mle_service_get_data_pointer(bufId); 00194 00195 ptr = mle_tlv_write_version(ptr, cur->thread_info->version); 00196 ptr = mle_general_write_source_address(ptr, cur); 00197 ptr = thread_leader_data_tlv_write(ptr, cur); 00198 00199 tr_debug("Synch Req"); 00200 00201 if (mle_service_update_length_by_ptr(bufId, ptr) != 0) { 00202 tr_debug("Buffer overflow at message write"); 00203 } 00204 00205 mle_service_set_packet_callback(bufId, thread_link_request_timeout); 00206 mle_service_set_msg_destination_address(bufId, router_ll64); 00207 mle_service_set_msg_timeout_parameters(bufId, &timeout); 00208 mle_service_send_message(bufId); 00209 return 0; 00210 } 00211 00212 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, mac_neighbor_table_entry_t *neighbor) 00213 { 00214 int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv); 00215 00216 if (leaderDataUpdate == 1) { 00217 if (neighbor && neighbor->connected_device == 1) { 00218 // Request network data if we have a 2-way link 00219 tr_debug("Request New Network Data from %s", trace_ipv6(src_address)); 00220 thread_network_data_request_send(cur, src_address, true); 00221 } 00222 } else if (leaderDataUpdate == 2) { 00223 tr_debug("Start Merge"); 00224 thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL); 00225 return false; 00226 00227 } else if (leaderDataUpdate < 0) { 00228 tr_warn("Leader data failure"); 00229 return false; 00230 } 00231 return true; 00232 } 00233 00234 static bool thread_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data) 00235 { 00236 if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) { 00237 return true; 00238 } 00239 if (heard_partition_leader_data.weighting == thread_info(cur)->thread_leader_data->weighting && 00240 heard_partition_leader_data.partitionId < thread_info(cur)->thread_leader_data->partitionId) { 00241 return true; 00242 } 00243 return false; 00244 } 00245 00246 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) 00247 { 00248 //Read Leader Data and verify connectivity 00249 // Leader data is mandatory 00250 if (!thread_leader_data_parse(ptr, data_length, leaderData)) { 00251 return false; 00252 } 00253 00254 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) { 00255 return false; 00256 } 00257 00258 if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) { 00259 if (thread_is_router_addr(*shortAddress)) { 00260 //Sender is reeds 00261 return false; 00262 } 00263 routeTlv->dataPtr = NULL; 00264 routeTlv->tlvLen = 0; 00265 } 00266 return true; 00267 } 00268 00269 static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mac_neighbor_table_entry_t *entry_temp, uint16_t short_address) 00270 { 00271 if (!entry_temp) { 00272 return; 00273 } 00274 00275 uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm); 00276 mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex); 00277 00278 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false); 00279 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00280 00281 if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) { 00282 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime ); 00283 } 00284 00285 if (short_address != entry_temp->mac16 ) { 00286 if (thread_router_addr_from_addr(entry_temp->mac16 ) == cur->thread_info->routerShortAddress) { 00287 thread_dynamic_storage_child_info_clear(cur->id, entry_temp); 00288 protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16 ); 00289 } 00290 entry_temp->mac16 = short_address; 00291 /* throw MLME_GET request, short address is changed automatically in get request callback */ 00292 mlme_get_t get_req; 00293 get_req.attr = macDeviceTable; 00294 get_req.attr_index = entry_temp->index ; 00295 cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req); 00296 } 00297 00298 return; 00299 } 00300 00301 static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address) 00302 { 00303 //check if network data needs to be requested 00304 if (!thread_bootstrap_request_network_data(cur, leader_data, short_address)) { 00305 tr_debug("Parent short address changed - re-attach"); 00306 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00307 return false; 00308 } 00309 00310 return true; 00311 } 00312 00313 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) 00314 { 00315 mle_tlv_info_t routeTlv; 00316 thread_leader_data_t leaderData; 00317 mac_neighbor_table_entry_t *entry_temp; 00318 uint16_t shortAddress; 00319 bool adv_from_my_partition; 00320 bool my_parent; 00321 00322 // Check device mode & bootstrap state 00323 if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) || 00324 (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) { 00325 return; 00326 } 00327 00328 tr_debug("Received Advertisement"); 00329 00330 // Validate and parse TLV's 00331 if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) { 00332 return; 00333 } 00334 00335 // Get MLE entry 00336 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); 00337 if (entry_temp) { 00338 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false); 00339 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00340 } 00341 00342 // Check if this is from my parent 00343 my_parent = thread_check_is_this_my_parent(cur, entry_temp); 00344 00345 adv_from_my_partition = thread_partition_match(cur, &leaderData); 00346 00347 if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) { 00348 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00349 } 00350 00351 if (entry_temp && !adv_from_my_partition && !my_parent) { 00352 // Remove MLE entry that are located in other partition and is not my parent 00353 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp); 00354 entry_temp = NULL; 00355 } 00356 00357 /* Check parent status */ 00358 if (!thread_attach_active_router(cur) && my_parent) { 00359 if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) { 00360 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp); 00361 return; 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 /* REED and FED */ 00371 if (!thread_attach_active_router(cur)) { 00372 /* Check if advertisement is from same partition */ 00373 if (thread_partition_match(cur, &leaderData)) { 00374 if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) { 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 /* Advertisement from higher / lower partition */ 00380 } else { 00381 // Check if better partition is heard 00382 if (thread_bootstrap_partition_process(cur, thread_get_router_count_from_route_tlv(&routeTlv), &leaderData, &routeTlv) > 0) { 00383 tr_debug("Start Merge"); 00384 thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL); 00385 return; 00386 } 00387 00388 // REED advertisement to lower partition to help merge faster 00389 if (thread_heard_lower_partition(cur, leaderData)) { 00390 thread_router_bootstrap_reed_merge_advertisement(cur); 00391 } 00392 } 00393 /* ROUTER */ 00394 } else { 00395 if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp)) { 00396 return; 00397 } 00398 thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress); 00399 } 00400 } 00401 00402 // Process route TLV 00403 if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) && thread_partition_match(cur, &leaderData)) { 00404 tr_debug("Update Route TLV %x", entry_temp->mac16 ); 00405 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen, linkMargin, entry_temp); 00406 } 00407 } 00408 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) 00409 { 00410 uint32_t llFrameCounter; 00411 uint32_t mleFrameCounter; 00412 uint16_t version, shortAddress; 00413 uint16_t messageId; 00414 uint8_t linkMarginfronNeigh; 00415 mac_neighbor_table_entry_t *entry_temp; 00416 bool createNew, new_entry_created; 00417 00418 tr_info("MLE LINK ACCEPT"); 00419 00420 messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); 00421 00422 if (messageId == 0) { 00423 tr_debug("No matching challenge"); 00424 return; 00425 } 00426 00427 if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) { 00428 //Free Response only if it is unicast 00429 mle_service_msg_free(messageId); 00430 } 00431 00432 // TODO: Check missing TLV's 00433 if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) || 00434 (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) || 00435 (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) { 00436 return; 00437 } 00438 00439 /* Call to determine whether or not we should create a new link */ 00440 createNew = thread_bootstrap_link_create_check(cur, shortAddress); 00441 00442 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, createNew, &new_entry_created); 00443 00444 if (!entry_temp) { 00445 thread_link_reject_send(cur, mle_msg->packet_src_address); 00446 return; 00447 } 00448 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, new_entry_created); 00449 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00450 00451 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00452 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00453 } 00454 00455 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter 00456 if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) { 00457 mleFrameCounter = llFrameCounter; 00458 } 00459 00460 entry_temp->mac16 = shortAddress; 00461 mle_service_frame_counter_entry_add(cur->id, entry_temp->index , mleFrameCounter); 00462 // Set full data as REED needs full data and SED will not make links 00463 thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index , true); 00464 mlme_device_descriptor_t device_desc; 00465 mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 , llFrameCounter, false); 00466 mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , security_headers->KeyIndex, new_entry_created); 00467 uint32_t timeout; 00468 00469 if (new_entry_created) { 00470 timeout = THREAD_DEFAULT_LINK_LIFETIME; 00471 } else { 00472 timeout = entry_temp->link_lifetime ; 00473 } 00474 00475 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); 00476 00477 if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->mac16 )) { 00478 // If we both are routers, mark the link as 2-way 00479 entry_temp->connected_device = 1; 00480 tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->connected_device ); 00481 } else { 00482 tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->connected_device ); 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->mac16 , 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 && 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 && 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 mac_neighbor_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 = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); 00564 00565 if (entry_temp) { 00566 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false); 00567 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00568 } 00569 00570 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER || 00571 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 00572 if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) { 00573 // We are attached as child and just learn new data 00574 if (!thread_check_is_this_my_parent(cur, entry_temp)) { 00575 return; 00576 } 00577 } else { 00578 if (!thread_partition_match(cur, &leaderData)) { 00579 // if receiving data response from different partition it is dropped 00580 return; 00581 } 00582 } 00583 } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 00584 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00585 if (!entry_temp) { 00586 tr_debug("Unknown neighbor"); 00587 return; 00588 } 00589 } 00590 00591 if (!thread_partition_match(cur, &leaderData)) { 00592 thread_partition_info_update(cur, &leaderData); 00593 accept_new_data = true; 00594 } 00595 00596 //check response is for link metrics query 00597 thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length); 00598 00599 if (cur->thread_info->networkDataRequested) { 00600 tr_debug("Requested network data received"); 00601 cur->thread_info->networkDataRequested = false; 00602 accept_new_data = true; 00603 } 00604 if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) { 00605 tr_debug("Network data updated"); 00606 accept_new_data = true; 00607 } 00608 // update operational datasets 00609 00610 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00611 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00612 thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00613 } 00614 // TODO check if result is true then need to update all configurations 00615 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00616 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00617 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00618 } 00619 // Check if we are now in sync 00620 // if not matching must send data request again 00621 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp 00622 || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00623 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00624 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00625 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00626 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00627 return; 00628 } 00629 //Check Network Data TLV 00630 if (accept_new_data) { 00631 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00632 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00633 thread_bootstrap_network_data_update(cur); 00634 } else { 00635 tr_debug("SET NWK data Request state"); 00636 } 00637 } 00638 00639 // leader has finished synching network data after reset/restart 00640 if (cur->thread_info->leader_synced) { 00641 cur->thread_info->leader_synced = false; 00642 thread_leader_service_network_data_changed(cur, true, true); 00643 } 00644 } 00645 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) 00646 { 00647 uint16_t len = 150 + 64; 00648 uint8_t mode; 00649 uint32_t keySequence; 00650 uint8_t *ptr; 00651 if (!thread_info(cur)) { 00652 return -1; 00653 } 00654 00655 uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE); 00656 00657 if (bufId == 0) { 00658 return -1; 00659 } 00660 00661 tr_debug("MLE Child update response"); 00662 00663 thread_management_get_current_keysequence(cur->id, &keySequence); 00664 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 00665 00666 ptr = mle_service_get_data_pointer(bufId); 00667 00668 mode = thread_mode_get_by_interface_ptr(cur); 00669 00670 //Write Mode Allways 00671 ptr = mle_tlv_write_mode(ptr, mode); 00672 //Set SRC 00673 ptr = mle_general_write_source_address(ptr, cur); 00674 //SET leader data 00675 ptr = thread_leader_data_tlv_write(ptr, cur); 00676 00677 //Set Addresss TLV 00678 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr, requestTlv->tlvLen, MLE_TYPE_ADDRESS_REGISTRATION) && 00679 (mode & MLE_FFD_DEV) == 0) { 00680 ptr = thread_address_registration_tlv_write(ptr, cur); 00681 } 00682 00683 if (requestTlv && mle_tlv_requested(requestTlv->dataPtr, requestTlv->tlvLen, MLE_TYPE_TIMEOUT)) { 00684 ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout); 00685 } 00686 00687 if (challengeTlv && challengeTlv->tlvLen) { 00688 ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen); 00689 ptr = mle_general_write_link_layer_framecounter(ptr, cur); 00690 //SET MLE Frame Counter 00691 ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id)); 00692 } 00693 00694 if (mle_service_update_length_by_ptr(bufId, ptr) != 0) { 00695 tr_debug("Buffer overflow at message write"); 00696 } 00697 mle_service_set_msg_destination_address(bufId, dst_address); 00698 mle_service_send_message(bufId); 00699 return 0; 00700 } 00701 00702 static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info) 00703 { 00704 uint8_t context; 00705 uint16_t length = tlv_info->tlvLen; 00706 uint8_t *ptr = tlv_info->dataPtr; 00707 00708 while (length) { 00709 context = *ptr++; 00710 if (context & 0x80) { 00711 if (memcmp(ptr, entry->address + 8, 8) == 0) { 00712 return true; 00713 } 00714 ptr += 8; 00715 length -= 9; 00716 } else { 00717 if (memcmp(ptr, entry->address, 16) == 0) { 00718 return true; 00719 } 00720 ptr += 16; 00721 length -= 17; 00722 } 00723 } 00724 00725 return false; 00726 00727 } 00728 00729 static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info) 00730 { 00731 bool ret_val = true; 00732 00733 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { 00734 if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL && 00735 !thread_addr_is_mesh_local_16(e->address, cur))) { 00736 00737 if (thread_address_registration_tlv_search(e, tlv_info) == false) { 00738 tr_debug("Address %s registration to parent failed", trace_ipv6(e->address)); 00739 addr_set_preferred_lifetime(cur, e, 0); // deprecate address 00740 ret_val = false; 00741 } else if (e->preferred_lifetime == 0) { 00742 addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite 00743 } 00744 } 00745 } 00746 thread_bootstrap_child_address_registration_response_process(cur); 00747 00748 return ret_val; 00749 } 00750 00751 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) 00752 { 00753 thread_leader_data_t leaderData; 00754 mle_tlv_info_t networkDataTlv; 00755 mle_tlv_info_t ConfigurationTlv; 00756 mle_tlv_info_t challengeTlv; 00757 mle_tlv_info_t tlv_req; 00758 uint64_t active_timestamp = 0; 00759 uint64_t pending_timestamp = 0;// means no pending timestamp 00760 mac_neighbor_table_entry_t *entry_temp; 00761 bool data_request_needed = false; 00762 mle_tlv_info_t tlv_info = {MLE_TYPE_SRC_ADDRESS, 0, 0}; 00763 00764 tr_debug("Child update request"); 00765 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); 00766 00767 if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) || 00768 !entry_temp || 00769 !thread_check_is_this_my_parent(cur, entry_temp)) { 00770 // Dropped if no leader data or not from parent 00771 tr_warn("invalid message"); 00772 return; 00773 } 00774 00775 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false); 00776 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00777 00778 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00779 mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req); 00780 00781 // Check if partition changed 00782 if (!thread_partition_match(cur, &leaderData)) { 00783 thread_partition_info_update(cur, &leaderData); 00784 } 00785 //Check Network Data TLV 00786 if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) { 00787 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen); 00788 thread_bootstrap_network_data_update(cur); 00789 } 00790 00791 // Check Address Registration TLV 00792 if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { 00793 thread_address_registration_tlv_check(cur, &tlv_info); 00794 } 00795 00796 if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || 00797 thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { 00798 // version numbers not in sync need to send data request 00799 data_request_needed = true; 00800 } 00801 00802 // update operational datasets 00803 mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00804 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) { 00805 thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp); 00806 } 00807 mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv); 00808 if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) { 00809 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen); 00810 } 00811 // Check if operational datasets are in sync 00812 if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp || 00813 thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) { 00814 tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64, 00815 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id), 00816 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id)); 00817 data_request_needed = true; 00818 } 00819 thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req); 00820 00821 if (data_request_needed) { 00822 thread_network_data_request_send(cur, mle_msg->packet_src_address, true); 00823 } 00824 } 00825 00826 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) 00827 { 00828 uint8_t mode; 00829 uint32_t timeout; 00830 mac_neighbor_table_entry_t *entry_temp; 00831 thread_leader_data_t leaderData = {0}; 00832 uint8_t status; 00833 bool leader_data_received; 00834 mle_tlv_info_t tlv_info = {MLE_TYPE_SRC_ADDRESS, 0, 0}; 00835 00836 if (cur->thread_info->thread_endnode_parent == NULL) { 00837 return; 00838 } 00839 00840 tr_debug("Child Update Response"); 00841 00842 //mle_service_buffer_find 00843 leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData); 00844 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); 00845 00846 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) && 00847 status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) { 00848 tr_debug("parent has connection error"); 00849 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp); 00850 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL); 00851 return; 00852 } 00853 00854 if (!entry_temp) { 00855 tr_debug("Not Neighbor"); 00856 mle_tlv_info_t challengeTlv; 00857 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv); 00858 thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv); 00859 return; 00860 } 00861 00862 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { 00863 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false); 00864 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index ); 00865 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); 00866 } else { 00867 tr_debug("Key ID Mode 2 not used; dropped."); 00868 return; 00869 } 00870 00871 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) { 00872 tr_debug("No Mode"); 00873 return; 00874 } 00875 00876 timeout = cur->thread_info->host_link_timeout; 00877 if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) { 00878 tr_debug("Setting child timeout, value=%"PRIu32, timeout); 00879 } 00880 00881 if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { 00882 thread_address_registration_tlv_check(cur, &tlv_info); 00883 } 00884 00885 tr_debug("Keep-Alive -->Respond from Parent"); 00886 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); 00887 00888 //Save possible new Leader Data 00889 if (leader_data_received) { 00890 thread_save_leader_data(cur, &leaderData); 00891 } 00892 00893 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00894 if (cur->thread_info->childUpdateReqTimer < 1) { 00895 cur->thread_info->childUpdateReqTimer = 0.8 * timeout; 00896 } 00897 } 00898 //This process is ready 00899 cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false; 00900 if (cur->thread_info->thread_endnode_parent->childUpdatePending) { 00901 tr_debug("Child Update Pending"); 00902 thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT); 00903 return; 00904 } 00905 00906 mac_data_poll_protocol_poll_mode_decrement(cur); 00907 00908 } 00909 00910 #endif
Generated on Tue Jul 12 2022 13:54:59 by
