Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_test_api.c Source File

thread_test_api.c

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