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_test_api.c
00001 /* 00002 * Copyright (c) 2014-2018, 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 00031 #include <string.h> 00032 #include <ns_list.h> 00033 #include <nsdynmemLIB.h> 00034 #include <net_thread_test.h> 00035 #include "randLIB.h" 00036 00037 #include "ns_trace.h" 00038 #include "common_functions.h" 00039 #include "NWK_INTERFACE/Include/protocol.h" 00040 #include "NWK_INTERFACE/Include/protocol_abstract.h" 00041 #include "6LoWPAN/Thread/thread_config.h" 00042 #include "6LoWPAN/Thread/thread_common.h" 00043 #include "6LoWPAN/Thread/thread_routing.h" 00044 #include "6LoWPAN/Thread/thread_joiner_application.h" 00045 #include "6LoWPAN/Thread/thread_leader_service.h" 00046 #include "6LoWPAN/Thread/thread_management_internal.h" 00047 #include "6LoWPAN/Thread/thread_bootstrap.h" 00048 #include "6LoWPAN/Thread/thread_router_bootstrap.h" 00049 #include "6LoWPAN/Thread/thread_discovery.h" 00050 #include "6LoWPAN/Thread/thread_nvm_store.h" 00051 #include "6LoWPAN/Thread/thread_extension_bootstrap.h" 00052 #include "6LoWPAN/Thread/thread_neighbor_class.h" 00053 #include "MLE/mle.h" 00054 #include "thread_meshcop_lib.h" 00055 #include "thread_diagcop_lib.h" 00056 #include "coap_service_api.h" 00057 #include "Service_Libs/mle_service/mle_service_api.h" 00058 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00059 #include "6LoWPAN/MAC/mac_helper.h" 00060 00061 #define TRACE_GROUP "tapi" 00062 00063 00064 int_fast8_t arm_nwk_6lowpan_thread_test_add_neighbour( 00065 int8_t interface_id, 00066 uint16_t neighbour_short_addr, 00067 uint_fast8_t link_margin_db, 00068 uint8_t id_sequence, 00069 const uint8_t *id_mask, 00070 const uint8_t *route_data) 00071 { 00072 #ifdef HAVE_THREAD 00073 protocol_interface_info_entry_t *cur; 00074 cur = protocol_stack_interface_info_get_by_id(interface_id); 00075 if (!cur) { 00076 tr_warn("Invalid interface id"); 00077 return -1; 00078 } 00079 00080 return thread_routing_add_link(cur, neighbour_short_addr, link_margin_db, id_sequence, id_mask, route_data, true); 00081 #else 00082 (void)interface_id; 00083 (void)neighbour_short_addr; 00084 (void)link_margin_db; 00085 (void)id_sequence; 00086 (void)id_mask; 00087 (void)route_data; 00088 return -1; 00089 #endif 00090 } 00091 00092 int_fast8_t arm_nwk_6lowpan_thread_test_remove_neighbour( 00093 int8_t interface_id, 00094 uint16_t neighbour_short_addr) 00095 { 00096 #ifdef HAVE_THREAD 00097 protocol_interface_info_entry_t *cur; 00098 cur = protocol_stack_interface_info_get_by_id(interface_id); 00099 if (!cur) { 00100 tr_warn("Invalid interface id"); 00101 return -1; 00102 } 00103 00104 return thread_routing_remove_link(cur, neighbour_short_addr); 00105 #else 00106 (void)interface_id; 00107 (void)neighbour_short_addr; 00108 return -1; 00109 #endif 00110 00111 } 00112 00113 void arm_nwk_6lowpan_thread_test_print_routing_database(int8_t interface_id) 00114 { 00115 #if defined(FEA_TRACE_SUPPORT) && defined(HAVE_THREAD) 00116 const protocol_interface_info_entry_t *cur; 00117 00118 cur = protocol_stack_interface_info_get_by_id(interface_id); 00119 if (!cur) { 00120 tr_warn("Invalid interface id"); 00121 return; 00122 } 00123 00124 const thread_info_t *thread = cur->thread_info; 00125 if (!thread) { 00126 tr_warn("Thread not active"); 00127 return; 00128 } 00129 00130 //tr_debug("Thread routing database"); 00131 if (thread_i_am_router(cur)) { 00132 tr_info("I am Thread Router (ID: %d)", thread_router_id_from_addr(mac_helper_mac16_address_get(cur))); 00133 } else { 00134 tr_info("I am not a Thread Router"); 00135 } 00136 //tr_debug("Router ID Set + Current Route:"); 00137 if (thread_i_am_router(cur)) { 00138 for (int r = 0; r < N_THREAD_ROUTERS; r++) { 00139 if (thread->routing.fast_route_table[r] != FAST_ROUTE_INVALID_ID) { 00140 if (thread->routing.fast_route_table[r] == FAST_ROUTE_NO_ROUTE) { 00141 tr_debug("Current Route - fast no route: %d -> ?", r); 00142 } else { 00143 tr_debug("Current Route - fast route: %d -> %d", r, thread->routing.fast_route_table[r]); 00144 } 00145 } 00146 } 00147 } 00148 00149 ns_list_foreach(const thread_router_link_t, n, &thread->routing.link_set) { 00150 tr_debug("Link Set - Id:%d Margin:%d.%x InQ:%d OutQ:%d As good:%d Age:%ds", 00151 n->router_id, 00152 n->link_margin >> THREAD_LINK_MARGIN_SCALING, 00153 n->link_margin & ((1 << THREAD_LINK_MARGIN_SCALING) - 1), 00154 n->incoming_quality, 00155 n->outgoing_quality, 00156 n->as_good, 00157 n->age / 10); 00158 } 00159 00160 if (thread_i_am_router(cur)) { 00161 ns_list_foreach(const thread_route_t, route, &thread->routing.route_set) { 00162 tr_debug("Route Set - Dest:%d Next hop:%d Cost:%d", 00163 route->destination, 00164 route->next_hop, 00165 route->route_cost); 00166 } 00167 } 00168 #else 00169 (void)interface_id; 00170 #endif 00171 } 00172 00173 int8_t thread_routing_set_network_id_timeout(int8_t interface_id, uint16_t network_id_timeout) 00174 { 00175 #ifdef HAVE_THREAD 00176 const protocol_interface_info_entry_t *cur; 00177 00178 if( network_id_timeout < 5 ) { 00179 tr_warn("Too small timeout value, min: 5"); 00180 return -3; 00181 } 00182 00183 cur = protocol_stack_interface_info_get_by_id(interface_id); 00184 if (!cur) { 00185 tr_warn("Invalid interface id"); 00186 return -1; 00187 } 00188 if (!cur->thread_info) { 00189 tr_warn("Thread not active"); 00190 return -2; 00191 } 00192 cur->thread_info->routing.networkIdTimeout = network_id_timeout; 00193 return 0; 00194 #else 00195 (void)interface_id; 00196 (void)network_id_timeout; 00197 return -1; 00198 #endif 00199 } 00200 00201 int8_t thread_routing_get_network_id_timeout(int8_t interface_id, uint16_t *network_id_timeout) 00202 { 00203 #ifdef HAVE_THREAD 00204 const protocol_interface_info_entry_t *cur; 00205 00206 if(!network_id_timeout) { 00207 tr_warn("Invalid input ptr"); 00208 return -3; 00209 } 00210 cur = protocol_stack_interface_info_get_by_id(interface_id); 00211 if (!cur) { 00212 tr_warn("Invalid interface id"); 00213 return -1; 00214 } 00215 if (!cur->thread_info) { 00216 tr_warn("Thread not active"); 00217 return -2; 00218 } 00219 *network_id_timeout = cur->thread_info->routing.networkIdTimeout; 00220 return 0; 00221 #else 00222 (void)interface_id; 00223 (void)network_id_timeout; 00224 return -1; 00225 #endif 00226 } 00227 00228 int thread_test_set_context_id_reuse_timeout( 00229 int8_t interface_id, 00230 uint32_t timeout) 00231 { 00232 #ifdef HAVE_THREAD 00233 protocol_interface_info_entry_t *cur; 00234 00235 if (timeout < 60 || timeout > THREAD_CONTEXT_ID_REUSE_TIMEOUT) { 00236 return -1; 00237 } 00238 00239 cur = protocol_stack_interface_info_get_by_id(interface_id); 00240 if (!cur) { 00241 tr_warn("Invalid interface id"); 00242 return -1; 00243 } 00244 00245 if (!cur->thread_info) { 00246 tr_warn("Not Thread specific interface"); 00247 return -1; 00248 } 00249 00250 cur->thread_info->networkDataStorage.contex_id_reuse_timeout = timeout; 00251 return 0; 00252 #else 00253 (void)interface_id; 00254 (void)timeout; 00255 return -1; 00256 #endif 00257 } 00258 00259 int thread_test_remove_router_by_id(int8_t interface_id, uint8_t routerId) 00260 { 00261 #ifdef HAVE_THREAD 00262 protocol_interface_info_entry_t *cur; 00263 cur = protocol_stack_interface_info_get_by_id(interface_id); 00264 00265 if (!cur) { 00266 return -1; 00267 } 00268 00269 if (!cur->thread_info) { 00270 return -1; 00271 } 00272 00273 if (!cur->thread_info->leader_private_data) { 00274 return -1; 00275 } 00276 00277 if (thread_attach_ready(cur) != 0) { 00278 return -1; 00279 } 00280 00281 if (routerId >= 64) { 00282 return -1; 00283 } 00284 00285 if (!thread_leader_service_route_mask_bit_clear(cur->thread_info->leader_private_data, routerId)) { 00286 return -1; 00287 } 00288 00289 tr_debug("Release Routerid %x", routerId); 00290 thread_leader_service_update_id_set(cur); 00291 00292 return 0; 00293 #else 00294 (void)interface_id; 00295 (void)routerId; 00296 return -1; 00297 #endif 00298 } 00299 00300 int thread_test_router_downgrade(int8_t interface_id) 00301 { 00302 #ifdef HAVE_THREAD 00303 protocol_interface_info_entry_t *cur; 00304 cur = protocol_stack_interface_info_get_by_id(interface_id); 00305 00306 if (!cur) { 00307 return -1; 00308 } 00309 00310 if (!cur->thread_info) { 00311 return -1; 00312 } 00313 00314 if (thread_attach_ready(cur) != 0) { 00315 return -1; 00316 } 00317 00318 tr_debug("Trigger REED router downgrade process"); 00319 thread_bootstrap_attached_downgrade_router(cur); 00320 00321 return 0; 00322 #else 00323 (void)interface_id; 00324 return -1; 00325 #endif 00326 } 00327 00328 int thread_test_print_network_data(int8_t interface_id) 00329 { 00330 #ifdef HAVE_THREAD 00331 protocol_interface_info_entry_t *cur; 00332 cur = protocol_stack_interface_info_get_by_id(interface_id); 00333 if (!cur) { 00334 return -1; 00335 } 00336 00337 if (!cur->thread_info) { 00338 return -1; 00339 } 00340 00341 00342 if (thread_attach_ready(cur) != 0) { 00343 return -1; 00344 } 00345 00346 thread_nd_network_data_print(&cur->thread_info->networkDataStorage, mac_helper_mac16_address_get(cur)); 00347 00348 return 0; 00349 #else 00350 (void)interface_id; 00351 return -1; 00352 #endif 00353 } 00354 00355 00356 int8_t thread_reed_set_advertisement_interval(int8_t interface_id, uint16_t advertisement_interval, uint16_t jitter_interval) 00357 { 00358 #ifdef HAVE_THREAD 00359 const protocol_interface_info_entry_t *cur; 00360 00361 if(!advertisement_interval) { 00362 tr_warn("Invalid input ptr"); 00363 return -3; 00364 } 00365 cur = protocol_stack_interface_info_get_by_id(interface_id); 00366 if (!cur) { 00367 tr_warn("Invalid interface id"); 00368 return -1; 00369 } 00370 if (!cur->thread_info) { 00371 tr_warn("Thread not active"); 00372 return -2; 00373 } 00374 if (!jitter_interval){ 00375 jitter_interval = 0; 00376 } 00377 cur->thread_info->routerSelectParameters.reedAdvertisementInterval = (uint16_t) advertisement_interval; 00378 cur->thread_info->routerSelectParameters.reedAdvertisementJitterInterval = (uint16_t) jitter_interval; 00379 tr_debug("new advertisement interval set to %d seconds and jitter %d seconds",(uint16_t) advertisement_interval, (uint16_t) jitter_interval); 00380 return 0; 00381 #else 00382 (void)interface_id; 00383 (void)advertisement_interval; 00384 (void)jitter_interval; 00385 return -1; 00386 #endif 00387 } 00388 00389 int thread_test_key_sequence_counter_update(int8_t interface_id, uint32_t thrKeySequenceCounter) 00390 { 00391 #ifdef HAVE_THREAD 00392 int ret_val = -1; 00393 protocol_interface_info_entry_t *cur; 00394 link_configuration_s *linkConfiguration; 00395 linkConfiguration = thread_joiner_application_get_config(interface_id); 00396 if (!linkConfiguration) { 00397 return -1; 00398 } 00399 00400 cur = protocol_stack_interface_info_get_by_id(interface_id); 00401 if (cur && cur->thread_info) { 00402 /* Not sure if this check is needed - not sure exactly what the flag means! */ 00403 if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { 00404 if (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) { 00405 if (thrKeySequenceCounter > linkConfiguration->key_sequence) { 00406 ret_val = thread_management_key_sets_calc(cur, linkConfiguration, thrKeySequenceCounter); 00407 } 00408 } 00409 } 00410 } 00411 return ret_val; 00412 #else 00413 (void)interface_id; 00414 (void)thrKeySequenceCounter; 00415 return -1; 00416 #endif 00417 } 00418 00419 int thread_test_stack_cache_reset(int8_t interface_id) 00420 { 00421 #ifdef HAVE_THREAD 00422 protocol_interface_info_entry_t *cur; 00423 00424 cur = protocol_stack_interface_info_get_by_id(interface_id); 00425 if (!cur) { 00426 tr_warn("Invalid interface id"); 00427 return -1; 00428 } 00429 00430 // Reset link information 00431 (void) thread_nvm_store_link_info_clear(); 00432 00433 return 0; 00434 #else 00435 (void)interface_id; 00436 return -1; 00437 #endif 00438 } 00439 00440 int thread_test_key_rotation_update(int8_t interface_id, uint32_t thrKeyRotation) 00441 { 00442 #ifdef HAVE_THREAD 00443 int ret_val = -1; 00444 protocol_interface_info_entry_t *cur; 00445 link_configuration_s *linkConfiguration; 00446 linkConfiguration = thread_joiner_application_get_config(interface_id); 00447 if (!linkConfiguration) { 00448 return -1; 00449 } 00450 00451 cur = protocol_stack_interface_info_get_by_id(interface_id); 00452 if (cur && cur->thread_info) { 00453 /* Not sure if this check is needed - not sure exactly what the flag means! */ 00454 if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { 00455 if (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) { 00456 linkConfiguration->key_rotation = thrKeyRotation; 00457 thread_key_guard_timer_calculate(cur, linkConfiguration, false); 00458 ret_val = 0; 00459 } 00460 } 00461 } 00462 return ret_val; 00463 #else 00464 (void)interface_id; 00465 (void)thrKeyRotation; 00466 return -1; 00467 #endif 00468 } 00469 00470 int thread_test_router_select_threshold_values_set( 00471 int8_t interface_id, 00472 uint8_t upgradeThreshold, 00473 uint8_t downgradeThreshold) 00474 { 00475 #ifdef HAVE_THREAD 00476 protocol_interface_info_entry_t *cur; 00477 if (downgradeThreshold == 0) { 00478 tr_warn("Invalid Threshold value"); 00479 return -1; 00480 } 00481 00482 if (upgradeThreshold >= downgradeThreshold) { 00483 tr_warn("Invalid Threshold value %u >= %u", upgradeThreshold, downgradeThreshold); 00484 return -1; 00485 } 00486 00487 cur = protocol_stack_interface_info_get_by_id(interface_id); 00488 if (!cur) { 00489 tr_warn("Invalid interface id"); 00490 return -1; 00491 } 00492 00493 if (!cur->thread_info) { 00494 tr_warn("Not Thread specific interface"); 00495 return -1; 00496 } 00497 00498 cur->thread_info->routerSelectParameters.routerUpgradeThresHold = upgradeThreshold; 00499 cur->thread_info->routerSelectParameters.routerDowngradeThresHold = downgradeThreshold; 00500 00501 return 0; 00502 #else 00503 (void)interface_id; 00504 (void)upgradeThreshold; 00505 (void)downgradeThreshold; 00506 return -1; 00507 #endif 00508 } 00509 int thread_test_max_accepted_router_id_limit_set( 00510 int8_t interface_id, 00511 uint8_t maxRouterLimit) 00512 { 00513 #ifdef HAVE_THREAD 00514 protocol_interface_info_entry_t *cur; 00515 if ((maxRouterLimit < 1) || (maxRouterLimit > 32)) { 00516 tr_error("Accept values are between 1-32 for max Router Id assign limit"); 00517 return -1; 00518 } 00519 00520 cur = protocol_stack_interface_info_get_by_id(interface_id); 00521 if (!cur) { 00522 tr_warn("Invalid interface id"); 00523 return -1; 00524 } 00525 00526 if (!cur->thread_info) { 00527 tr_warn("Not Thread specific interface"); 00528 return -1; 00529 } 00530 cur->thread_info->testMaxActiveRouterIdLimit = maxRouterLimit; 00531 tr_debug("New max Router Id assign limit is %u", maxRouterLimit); 00532 return 0; 00533 #else 00534 (void)interface_id; 00535 (void)maxRouterLimit; 00536 return -1; 00537 #endif 00538 } 00539 00540 00541 /** 00542 * Set Thread Security Master Key and Key Index 00543 * 00544 * \param interface_id Network Interface 00545 * \param enableSecurity Boolean for enable security or disable 00546 * \param threadMasterKey Thread Master Key material which will be used for generating new key 00547 * \param threadMasterKeyIndex Thread key material key index which will be increment periodically 00548 * \param keyRollPeriod Define Key index & key update process 00549 * 00550 * return 0, ADD OK 00551 * return <0 Add Not OK 00552 */ 00553 int thread_test_security_material_set(int8_t interface_id, bool enableSecurity, uint8_t *thrMasterKey, uint32_t thrKeySequenceCounter, uint32_t thrKeyRotation) 00554 { 00555 #ifdef HAVE_THREAD 00556 int ret_val = -1; 00557 uint8_t key_material[32]; 00558 uint8_t key_index; 00559 protocol_interface_info_entry_t *cur; 00560 link_configuration_s *linkConfiguration; 00561 linkConfiguration = thread_joiner_application_get_config(interface_id); 00562 if (!linkConfiguration) { 00563 return -1; 00564 } 00565 00566 cur = protocol_stack_interface_info_get_by_id(interface_id); 00567 if (!cur) { 00568 return -1; 00569 } 00570 00571 if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) { 00572 return -4; 00573 } 00574 00575 if (cur->thread_info) { 00576 00577 if (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) { 00578 mac_helper_link_frame_counter_set(cur->id, 0); 00579 if (enableSecurity) { 00580 if (thrMasterKey) { 00581 ret_val = 0; 00582 linkConfiguration->key_rotation = thrKeyRotation; 00583 linkConfiguration->key_sequence = thrKeySequenceCounter; 00584 cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY; 00585 cur->mac_parameters->mac_configured_sec_level = 5; 00586 cur->thread_info->masterSecretMaterial.historyKeyValid = false; 00587 cur->thread_info->masterSecretMaterial.valid_Info = true; 00588 memcpy(linkConfiguration->master_key, thrMasterKey, 16); 00589 cur->thread_info->masterSecretMaterial.keyRotation = thrKeyRotation; 00590 //Define KEY's 00591 thread_key_get(thrMasterKey, key_material, thrKeySequenceCounter); 00592 key_index = THREAD_KEY_INDEX(thrKeySequenceCounter); 00593 //Set Keys 00594 mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX); 00595 mle_service_security_set_security_key(cur->id, key_material, key_index, true); 00596 //Gen also Next Key 00597 thread_security_next_key_generate(cur, linkConfiguration->master_key, thrKeySequenceCounter); 00598 thread_key_guard_timer_calculate(cur, linkConfiguration, false); 00599 } 00600 } else { 00601 ret_val = 0; 00602 cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_NO_LINK_SECURITY; 00603 cur->mac_parameters->mac_configured_sec_level = 0; 00604 cur->thread_info->masterSecretMaterial.valid_Info = false; 00605 } 00606 if (ret_val == 0) { 00607 cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION; 00608 cur->configure_flags |= INTERFACE_SECURITY_DEFINED; 00609 } 00610 } 00611 } 00612 return ret_val; 00613 #else 00614 (void)interface_id; 00615 (void)enableSecurity; 00616 (void)thrMasterKey; 00617 (void)thrKeySequenceCounter; 00618 (void)thrKeyRotation; 00619 return -1; 00620 #endif 00621 } 00622 00623 int thread_test_version_set(int8_t interface_id, uint8_t version) 00624 { 00625 #ifdef HAVE_THREAD 00626 protocol_interface_info_entry_t *cur; 00627 thread_version = version; 00628 cur = protocol_stack_interface_info_get_by_id(interface_id); 00629 if (!cur) { 00630 /*We already stored the new Thread version above, so even if cur is NULL the version is updated.*/ 00631 return 0; 00632 } 00633 cur->thread_info->version = version; 00634 return 0; 00635 00636 #else 00637 (void)interface_id; 00638 return -1; 00639 #endif 00640 } 00641 int thread_test_router_selection_jitter_set(int8_t interface_id, uint32_t jitter) 00642 { 00643 #ifdef HAVE_THREAD 00644 protocol_interface_info_entry_t *cur; 00645 if (jitter < 1) { 00646 return -1; 00647 } 00648 thread_router_selection_jitter = jitter; 00649 cur = protocol_stack_interface_info_get_by_id(interface_id); 00650 if (cur && cur->thread_info && cur->thread_info->reedJitterTimer > jitter) { 00651 cur->thread_info->reedJitterTimer = thread_router_bootstrap_random_upgrade_jitter(); 00652 } 00653 return 0; 00654 00655 #else 00656 (void)interface_id; 00657 (void)jitter; 00658 return -1; 00659 #endif 00660 } 00661 00662 int thread_test_min_delay_timer_set(int8_t interface_id, uint32_t delay_timer_value) 00663 { 00664 #ifdef HAVE_THREAD 00665 (void)interface_id; 00666 if (delay_timer_value < 1) { 00667 return -1; 00668 } 00669 thread_delay_timer_default = delay_timer_value; 00670 return 0; 00671 00672 #else 00673 (void)interface_id; 00674 (void)delay_timer_value; 00675 return -1; 00676 #endif 00677 } 00678 00679 int thread_test_increment_key_sequence_counter(int8_t interface_id) 00680 { 00681 #ifdef HAVE_THREAD 00682 return thread_management_increment_key_sequence_counter(interface_id); 00683 #else 00684 (void)interface_id; 00685 return -1; 00686 #endif 00687 } 00688 #ifdef HAVE_THREAD 00689 static int thread_test_panid_conflict_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00690 { 00691 (void)source_address; 00692 (void)source_port; 00693 uint16_t panid; 00694 uint8_t *ptr; 00695 uint16_t len MAYBE_UNUSED; 00696 tr_debug("Thread test panid conflict request"); 00697 if (2 <= thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PANID, &panid)) { 00698 tr_info("PANID TLV %02x",panid); 00699 } 00700 if ( (len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &ptr)) > 0) { 00701 tr_info("Channel mask TLV %s",trace_array(ptr,len)); 00702 } 00703 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, NULL, 0); 00704 return 0; 00705 } 00706 #endif 00707 00708 #ifdef HAVE_THREAD 00709 static int thread_test_energy_scan_result_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00710 { 00711 (void)source_address; 00712 (void)source_port; 00713 uint8_t *ptr; 00714 uint16_t len MAYBE_UNUSED; 00715 00716 tr_debug("Thread test energy scan result"); 00717 if ( (len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &ptr)) > 0) { 00718 tr_info("Channel mask TLV %s",trace_array(ptr,len)); 00719 } 00720 if ( (len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_ENERGY_LIST, &ptr)) > 0) { 00721 tr_info("Energy list TLV %s",trace_array(ptr,len)); 00722 } 00723 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, NULL, 0); 00724 return 0; 00725 } 00726 #ifdef HAVE_THREAD 00727 static uint8_t coap_service = 0; 00728 static response_cb *generic_response_cb_ptr = NULL; 00729 static coap_response_cb *coap_response_cb_ptr = NULL; 00730 00731 static int thread_test_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00732 { 00733 (void)source_address; 00734 (void)source_port; 00735 00736 tr_debug("Thread test response received"); 00737 if (!response_ptr) { 00738 return -1; 00739 } 00740 /* Call callback function when receiving response, but do not call when receiving message code "empty" (Just ACK - not piggybacked response) */ 00741 if (generic_response_cb_ptr && (response_ptr->msg_code != COAP_MSG_CODE_EMPTY)) 00742 generic_response_cb_ptr(service_id, response_ptr->payload_ptr, response_ptr->payload_len); 00743 00744 if(response_ptr->uri_path_ptr && (!memcmp(response_ptr->uri_path_ptr, THREAD_URI_DIAGNOSTIC_ANSWER, strlen(THREAD_URI_DIAGNOSTIC_ANSWER)))){ 00745 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, response_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, NULL, 0); 00746 } 00747 return 0; 00748 } 00749 00750 static int thread_coap_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00751 { 00752 #ifndef HAVE_DEBUG 00753 (void) source_address; 00754 (void) source_port; 00755 #endif 00756 00757 tr_debug("Thread coap response received %s :%d",trace_ipv6(source_address),source_port); 00758 if (!response_ptr) { 00759 if (coap_response_cb_ptr) { 00760 coap_response_cb_ptr(service_id, 0xff, 0xff, NULL, 0); 00761 } 00762 return 0; 00763 } 00764 /* Call callback function when receiving response, but do not call when receiving message code "empty" (Just ACK - not piggybacked response) */ 00765 if (coap_response_cb_ptr && (response_ptr->msg_code != COAP_MSG_CODE_EMPTY)) { 00766 coap_response_cb_ptr(service_id, (uint8_t)(response_ptr->msg_code), (uint8_t)(response_ptr->msg_type), response_ptr->payload_ptr, response_ptr->payload_len); 00767 } 00768 00769 return 0; 00770 } 00771 00772 static int thread_coap_multicast_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00773 { 00774 #ifndef HAVE_DEBUG 00775 (void) source_address; 00776 (void) source_port; 00777 #endif 00778 00779 tr_debug("Thread coap multicast response received %s :%d",trace_ipv6(source_address),source_port); 00780 /* Call callback function when receiving response, but do not call when receiving message code "empty" (Just ACK - not piggybacked response) */ 00781 00782 if (coap_response_cb_ptr) { 00783 coap_response_cb_ptr(service_id, (uint8_t)(response_ptr->msg_code), (uint8_t)(response_ptr->msg_type), response_ptr->payload_ptr, response_ptr->payload_len); 00784 } 00785 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, response_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, NULL, 0); 00786 return 0; 00787 } 00788 #endif 00789 00790 static int thread_test_service_init(int8_t interface_id) 00791 { 00792 if (coap_service == 0) { 00793 coap_service = coap_service_initialize(interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 00794 coap_service_register_uri(coap_service, THREAD_URI_PANID_CONFLICT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_test_panid_conflict_cb); 00795 coap_service_register_uri(coap_service, THREAD_URI_ED_REPORT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_test_energy_scan_result_cb); 00796 coap_service_register_uri(coap_service, THREAD_URI_DIAGNOSTIC_ANSWER, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_coap_multicast_response_cb); 00797 } 00798 return 0; 00799 } 00800 00801 static uint8_t *channel_mask_write(uint8_t *ptr, uint8_t channel_page, uint8_t *mask_ptr) 00802 { 00803 uint8_t mask_len = 0; 00804 uint8_t mask_tlv[6];// 00805 if (channel_page == 0){ 00806 mask_len = 6; 00807 mask_tlv[0] = channel_page; 00808 mask_tlv[1] = 4; 00809 memcpy(&mask_tlv[2],mask_ptr,4); 00810 } 00811 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_CHANNEL_MASK, mask_len, mask_tlv); 00812 return ptr; 00813 } 00814 #endif 00815 int thread_test_panid_query_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint16_t panid, uint8_t channel_page, uint8_t *mask_ptr) 00816 { 00817 #ifdef HAVE_THREAD 00818 sn_coap_msg_type_e msg_type; 00819 uint8_t payload[16];// 2+6 + 2+2 + 2+2 00820 uint8_t *ptr; 00821 thread_test_service_init(interface_id); 00822 if (address_ptr[0] == 0xff){ 00823 msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00824 } else { 00825 msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00826 } 00827 ptr = payload; 00828 ptr = channel_mask_write(ptr, channel_page, mask_ptr); 00829 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_PANID, panid); 00830 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id); 00831 coap_service_request_send(coap_service, COAP_REQUEST_OPTIONS_NONE, address_ptr, THREAD_MANAGEMENT_PORT, 00832 msg_type, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_PANID_QUERY, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_test_response_cb); 00833 00834 return 0; 00835 #else 00836 (void)interface_id; 00837 (void)address_ptr; 00838 (void)session_id; 00839 (void)panid; 00840 (void)channel_page; 00841 (void)mask_ptr; 00842 return -1; 00843 #endif 00844 } 00845 int thread_test_energy_scan_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint8_t channel_page, uint8_t *mask_ptr, uint16_t period, uint8_t count, uint16_t duration) 00846 { 00847 #ifdef HAVE_THREAD 00848 sn_coap_msg_type_e msg_type; 00849 uint8_t payload[2+2 + 2+1 + 2+1 + 2+6 + 2+2]; 00850 uint8_t *ptr; 00851 thread_test_service_init(interface_id); 00852 if (address_ptr[0] == 0xff){ 00853 msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00854 } else { 00855 msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00856 } 00857 ptr = payload; 00858 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_PERIOD, period); 00859 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_COUNT, count); 00860 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_DURATION, duration); 00861 00862 ptr = channel_mask_write(ptr, channel_page, mask_ptr); 00863 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id); 00864 coap_service_request_send(coap_service, COAP_REQUEST_OPTIONS_NONE, address_ptr, THREAD_MANAGEMENT_PORT, 00865 msg_type, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ED_SCAN, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_test_response_cb); 00866 00867 return 0; 00868 #else 00869 (void)interface_id; 00870 (void)address_ptr; 00871 (void)session_id; 00872 (void)channel_page; 00873 (void)mask_ptr; 00874 (void)period; 00875 (void)count; 00876 (void)duration; 00877 return -1; 00878 #endif 00879 } 00880 00881 int thread_test_diagnostic_command_send(int8_t interface_id, uint8_t *address_ptr,const char *uri_ptr, uint8_t request_length, uint8_t *request_ptr, response_cb *resp_cb) 00882 { 00883 #ifdef HAVE_THREAD 00884 uint8_t payload[17+2] = {0}; 00885 uint8_t *ptr = NULL; 00886 generic_response_cb_ptr = resp_cb; 00887 sn_coap_msg_type_e msg_type; 00888 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_REQUEST_GET; 00889 00890 thread_test_service_init(interface_id); 00891 00892 if(request_length > 17 || !address_ptr) { 00893 return -1; 00894 } 00895 00896 if (address_ptr[0] == 0xff){ 00897 msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00898 } else { 00899 msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00900 } 00901 00902 if(!strcmp(uri_ptr, "d/dr")){ 00903 msg_code = COAP_MSG_CODE_REQUEST_POST; 00904 } 00905 00906 ptr = payload; 00907 if (request_length > 0 && request_ptr) { 00908 ptr = thread_diagcop_tlv_data_write(ptr, DIAGCOP_TLV_TYPE_LIST, request_length, request_ptr); 00909 } 00910 coap_service_request_send(coap_service, COAP_REQUEST_OPTIONS_NONE, address_ptr, THREAD_MANAGEMENT_PORT, 00911 msg_type, msg_code, uri_ptr, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_test_response_cb); 00912 00913 return 0; 00914 #else 00915 (void)interface_id; 00916 (void)address_ptr; 00917 (void)uri_ptr; 00918 (void)request_length; 00919 (void)request_ptr; 00920 (void)resp_cb; 00921 return -1; 00922 #endif 00923 } 00924 int thread_test_coap_request_send(int8_t interface_id, uint8_t *address_ptr, uint16_t port, uint8_t msg_type, uint8_t msg_code, uint16_t content_format, const char *uri_ptr, uint8_t *request_ptr, uint8_t request_length, coap_response_cb *resp_cb) 00925 { 00926 #ifdef HAVE_THREAD 00927 coap_response_cb_ptr = resp_cb; 00928 00929 thread_test_service_init(interface_id); 00930 00931 coap_service_request_send(coap_service, COAP_REQUEST_OPTIONS_NONE, address_ptr, port, 00932 (sn_coap_msg_type_e)msg_type, (sn_coap_msg_code_e)msg_code, uri_ptr, (sn_coap_content_format_e) content_format, request_ptr, request_length, thread_coap_response_cb); 00933 00934 return 0; 00935 #else 00936 (void)interface_id; 00937 (void)address_ptr; 00938 (void)port; 00939 (void)msg_type; 00940 (void)msg_code; 00941 (void)content_format; 00942 (void)uri_ptr; 00943 (void)request_length; 00944 (void)request_ptr; 00945 (void)resp_cb; 00946 return -1; 00947 #endif 00948 } 00949 00950 00951 int thread_test_announce_ntf_send(int8_t interface_id, uint8_t *address_ptr, uint32_t channel, uint16_t panid, uint64_t timestamp) 00952 { 00953 #ifdef HAVE_THREAD 00954 00955 (void)address_ptr; 00956 protocol_interface_info_entry_t *cur; 00957 cur = protocol_stack_interface_info_get_by_id(interface_id); 00958 if (!cur || !cur->thread_info ) { 00959 return -1; 00960 } 00961 return thread_bootstrap_announce_send(cur, (uint8_t)(channel >> 16), (uint16_t) channel, panid, timestamp, (uint16_t) channel); 00962 #else 00963 (void)interface_id; 00964 (void)address_ptr; 00965 (void)channel; 00966 (void)panid; 00967 (void)timestamp; 00968 return -1; 00969 #endif 00970 } 00971 00972 int thread_test_announce_begin_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint8_t channel_page, uint8_t *mask_ptr, uint16_t period, uint8_t count) 00973 { 00974 #ifdef HAVE_THREAD 00975 uint8_t payload[ 2+2 + 2+2 + 2+1 + 2+6]; 00976 uint8_t *ptr; 00977 sn_coap_msg_type_e msg_type; 00978 thread_test_service_init(interface_id); 00979 00980 if (address_ptr[0] == 0xff){ 00981 msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00982 } else { 00983 msg_type = COAP_MSG_TYPE_CONFIRMABLE; 00984 } 00985 00986 ptr = payload; 00987 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id); 00988 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_PERIOD, period); 00989 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_COUNT, count); 00990 ptr = channel_mask_write(ptr, channel_page, mask_ptr); 00991 coap_service_request_send(coap_service, COAP_REQUEST_OPTIONS_NONE, address_ptr, THREAD_MANAGEMENT_PORT, 00992 msg_type, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_MANAGEMENT_ANNOUNCE_BEGIN, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_test_response_cb); 00993 00994 return 0; 00995 #else 00996 (void)interface_id; 00997 (void)address_ptr; 00998 (void)session_id; 00999 (void)channel_page; 01000 (void)mask_ptr; 01001 (void)period; 01002 (void)count; 01003 return -1; 01004 #endif 01005 } 01006 01007 int thread_test_partition_info_get(int8_t interface_id, uint32_t *partition_id, uint8_t *weighting, uint8_t *data_version, uint8_t *stable_data_version, uint8_t *leader_id) 01008 { 01009 #ifdef HAVE_THREAD 01010 protocol_interface_info_entry_t *cur; 01011 cur = protocol_stack_interface_info_get_by_id(interface_id); 01012 if (!cur || !cur->thread_info || !cur->thread_info->thread_leader_data) { 01013 return -1; 01014 } 01015 01016 if (thread_attach_ready(cur) != 0) { 01017 return -1; 01018 } 01019 01020 if (partition_id) { 01021 *partition_id = cur->thread_info->thread_leader_data->partitionId; 01022 } 01023 if (weighting) { 01024 *weighting = cur->thread_info->thread_leader_data->weighting; 01025 } 01026 if (data_version) { 01027 *data_version = cur->thread_info->thread_leader_data->dataVersion; 01028 } 01029 if (stable_data_version) { 01030 *stable_data_version = cur->thread_info->thread_leader_data->stableDataVersion; 01031 } 01032 if (leader_id) { 01033 *leader_id = cur->thread_info->thread_leader_data->leaderRouterId; 01034 } 01035 return 0; 01036 #else 01037 (void)interface_id; 01038 (void)partition_id; 01039 (void)weighting; 01040 (void)data_version; 01041 (void)stable_data_version; 01042 (void)leader_id; 01043 return -1; 01044 #endif 01045 } 01046 int thread_test_partition_info_set(int8_t interface_id, uint32_t partition_id) 01047 { 01048 #ifdef HAVE_THREAD 01049 protocol_interface_info_entry_t *cur; 01050 cur = protocol_stack_interface_info_get_by_id(interface_id); 01051 if (!cur || !cur->thread_info ) { 01052 return -1; 01053 } 01054 cur->thread_info->testRandomPartitionId = partition_id; 01055 return 0; 01056 01057 #else 01058 (void)interface_id; 01059 (void)partition_id; 01060 return -1; 01061 #endif 01062 } 01063 int8_t thread_test_thread_information_get(int8_t interface_id, uint16_t *short_addr, uint8_t *router_count, bool *network_stable) 01064 { 01065 #ifdef HAVE_THREAD 01066 protocol_interface_info_entry_t *cur; 01067 cur = protocol_stack_interface_info_get_by_id(interface_id); 01068 if (!cur || !cur->thread_info) { 01069 return -1; 01070 } 01071 if (short_addr) { 01072 *short_addr = mac_helper_mac16_address_get(cur); 01073 } 01074 if (router_count) { 01075 *router_count = thread_routing_count_active_routers(&cur->thread_info->routing); 01076 } 01077 if (network_stable) { 01078 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE || 01079 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 01080 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { 01081 *network_stable = true; 01082 } else { 01083 *network_stable = !(thread_router_bootstrap_reed_upgrade(cur) || 01084 thread_router_bootstrap_router_downgrade(cur)); 01085 } 01086 01087 } 01088 return 0; 01089 #else 01090 (void)interface_id; 01091 (void)short_addr; 01092 (void)router_count; 01093 (void)network_stable; 01094 return -1; 01095 #endif 01096 } 01097 01098 01099 int8_t thread_test_child_count_get(int8_t interface_id) 01100 { 01101 #ifdef HAVE_THREAD 01102 protocol_interface_info_entry_t *cur; 01103 cur = protocol_stack_interface_info_get_by_id(interface_id); 01104 if (!cur || !cur->thread_info || !(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER)) { 01105 return -1; 01106 } 01107 return thread_router_bootstrap_child_count_get(cur); 01108 #else 01109 (void)interface_id; 01110 return -1; 01111 #endif 01112 } 01113 01114 int8_t thread_test_child_info_get(int8_t interface_id, uint8_t index, uint16_t *short_addr, bool *sleepy, uint8_t *mac64,uint8_t *margin) 01115 { 01116 #ifdef HAVE_THREAD 01117 protocol_interface_info_entry_t *cur; 01118 uint8_t n= 0; 01119 cur = protocol_stack_interface_info_get_by_id(interface_id); 01120 if (!cur || !cur->mac_parameters || !cur->thread_info || cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) { 01121 return -1; 01122 } 01123 uint16_t mac16 = mac_helper_mac16_address_get(cur); 01124 mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; 01125 if (!mac_table_list) { 01126 return -1; 01127 } 01128 01129 ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { 01130 if (thread_router_addr_from_addr(cur_entry->mac16) == thread_router_addr_from_addr(mac16)) { 01131 if (n == index) { 01132 *short_addr = cur_entry->mac16; 01133 memcpy(mac64,cur_entry->mac64, 8); 01134 *sleepy = cur_entry->rx_on_idle != true; 01135 *margin = thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, cur_entry->index); 01136 return 0; 01137 } 01138 n++; 01139 } 01140 } 01141 return -1; 01142 #else 01143 (void)interface_id; 01144 (void)index; 01145 (void)short_addr; 01146 (void)sleepy; 01147 (void)mac64; 01148 (void)margin; 01149 return -1; 01150 #endif 01151 } 01152 int8_t thread_test_neighbour_info_get(int8_t interface_id, uint8_t index, uint16_t *short_addr, uint8_t *mac64, uint8_t *margin) 01153 { 01154 #ifdef HAVE_THREAD 01155 protocol_interface_info_entry_t *cur; 01156 uint8_t n= 0; 01157 cur = protocol_stack_interface_info_get_by_id(interface_id); 01158 if (!cur || !cur->thread_info) { 01159 return -1; 01160 } 01161 uint16_t mac16 = mac_helper_mac16_address_get(cur); 01162 mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; 01163 if (!mac_table_list) { 01164 return -1; 01165 } 01166 01167 ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { 01168 if (thread_router_addr_from_addr(cur_entry->mac16) != thread_router_addr_from_addr(mac16)) { 01169 if (n == index) { 01170 *short_addr = cur_entry->mac16; 01171 memcpy(mac64,cur_entry->mac64, 8); 01172 *margin = thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, cur_entry->index); 01173 return 0; 01174 } 01175 n++; 01176 } 01177 } 01178 return -1; 01179 #else 01180 (void)interface_id; 01181 (void)index; 01182 (void)short_addr; 01183 (void)mac64; 01184 (void)margin; 01185 return -1; 01186 #endif 01187 } 01188 01189 int8_t thread_test_initial_slaac_iid_set(int8_t interface_id, uint8_t *iid) 01190 { 01191 #ifdef HAVE_THREAD 01192 (void)interface_id;// I somehow feel this might be needed later 01193 return addr_opaque_initial_iid_set(iid); 01194 #else 01195 (void)interface_id; 01196 (void)iid; 01197 return -1; 01198 #endif 01199 } 01200 01201 01202 int8_t thread_test_router_id_request_send(int8_t interface_id, uint8_t status) 01203 { 01204 #ifdef HAVE_THREAD 01205 protocol_interface_info_entry_t *cur; 01206 01207 cur = protocol_stack_interface_info_get_by_id(interface_id); 01208 if (!cur || !cur->thread_info) { 01209 return -1; 01210 } 01211 01212 if (thread_attach_ready(cur) != 0) { 01213 return -1; 01214 } 01215 01216 tr_debug("Trigger REED router upgrade process with status %d", status); 01217 01218 thread_router_bootstrap_router_id_request(cur, status); 01219 01220 return 0; 01221 #else 01222 (void)interface_id; 01223 (void)status; 01224 return -1; 01225 #endif 01226 01227 } 01228 01229 int8_t thread_test_router_address_set(int8_t interface_id, uint16_t router_address) 01230 { 01231 #ifdef HAVE_THREAD 01232 protocol_interface_info_entry_t *cur; 01233 cur = protocol_stack_interface_info_get_by_id(interface_id); 01234 if (!cur || !cur->thread_info) { 01235 return -1; 01236 } 01237 if ((router_address & THREAD_ROUTER_MASK) == THREAD_ROUTER_MASK) { 01238 tr_warn("address requested is reserved for anycast locator"); 01239 return -2; 01240 } 01241 if (cur->thread_info->routerShortAddress != 0xfffe) { 01242 tr_debug("router short address already present"); 01243 return -3; 01244 } 01245 cur->thread_info->routerShortAddress = router_address; 01246 return 0; 01247 #else 01248 (void)interface_id; 01249 (void)router_address; 01250 return -1; 01251 #endif 01252 } 01253 01254 int8_t thread_test_joiner_router_joiner_port_set(uint16_t port) 01255 { 01256 #ifdef HAVE_THREAD 01257 /* If parameter is '0', then use default port */ 01258 if (0 == port) { 01259 port = THREAD_DEFAULT_JOINER_PORT; 01260 } 01261 01262 thread_joiner_port = port; 01263 return 0; 01264 #else 01265 (void)port; 01266 return -1; 01267 #endif 01268 01269 } 01270 01271 int thread_test_mle_message_send(int8_t interface_id, uint8_t *dst_address, uint8_t msg_id, bool write_src_addr, bool write_leader_data, bool write_network_data, bool write_timestamp, bool write_operational_set, bool write_challenge, uint8_t *msg_ptr, uint8_t msg_len) 01272 { 01273 #ifdef HAVE_THREAD 01274 protocol_interface_info_entry_t *cur; 01275 uint16_t len = 32; 01276 uint32_t keySequence; 01277 uint8_t *ptr; 01278 cur = protocol_stack_interface_info_get_by_id(interface_id); 01279 if (!cur || !cur->thread_info) { 01280 return -1; 01281 } 01282 01283 len += msg_len; 01284 if (write_operational_set) { 01285 len += thread_active_operational_dataset_size(cur); 01286 len += thread_pending_operational_dataset_size(cur); 01287 } 01288 if (write_network_data) { 01289 len += thread_network_data_tlv_size(cur, true); 01290 } 01291 01292 uint16_t bufId = mle_service_msg_allocate(cur->id, len, write_challenge, msg_id); 01293 01294 if (bufId == 0) { 01295 return -1; 01296 } 01297 01298 tr_debug("thread test send MLE message"); 01299 01300 thread_management_get_current_keysequence(cur->id, &keySequence); 01301 mle_service_msg_update_security_params(bufId, 5, 2, keySequence); 01302 01303 ptr = mle_service_get_data_pointer(bufId); 01304 01305 //Set SRC 01306 if (write_src_addr) { 01307 ptr = mle_general_write_source_address(ptr, cur); 01308 } 01309 //SET leader data 01310 if (write_leader_data) { 01311 ptr = thread_leader_data_tlv_write(ptr, cur); 01312 } 01313 if (write_timestamp) { 01314 ptr = thread_active_timestamp_write(cur,ptr); 01315 ptr = thread_pending_operational_dataset_write(cur, ptr); 01316 } 01317 01318 if (write_operational_set) { 01319 ptr = thread_active_operational_dataset_write(cur, ptr); 01320 ptr = thread_pending_operational_dataset_write(cur, ptr); 01321 } 01322 if (write_network_data) { 01323 ptr = thread_network_data_tlv_write(cur, ptr, true); 01324 } 01325 // Add any user decided TLVs 01326 if (msg_ptr && msg_len) { 01327 memcpy(ptr,msg_ptr,msg_len); 01328 ptr += msg_len; 01329 } 01330 01331 if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) { 01332 tr_debug("Buffer overflow at message write"); 01333 } 01334 mle_service_set_msg_destination_address(bufId, dst_address); 01335 mle_service_send_message(bufId); 01336 return 0; 01337 #else 01338 (void)interface_id; 01339 (void)dst_address; 01340 (void)msg_id; 01341 (void)write_src_addr; 01342 (void)write_leader_data; 01343 (void)write_operational_set; 01344 (void)write_challenge; 01345 (void)msg_ptr; 01346 (void)msg_len; 01347 return -1; 01348 #endif 01349 } 01350 01351 01352 int thread_test_extension_name_set(int8_t interface_id, char extension_name[16]) 01353 { 01354 (void) interface_id; 01355 (void) extension_name; 01356 #ifdef HAVE_THREAD 01357 protocol_interface_info_entry_t *cur; 01358 01359 cur = protocol_stack_interface_info_get_by_id(interface_id); 01360 if (!cur || !cur->thread_info) { 01361 return -1; 01362 } 01363 01364 return thread_extension_bootstrap_thread_name_set(cur, extension_name); 01365 #else 01366 return -1; 01367 #endif 01368 }
Generated on Tue Aug 9 2022 00:37:23 by
