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