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