Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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-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 }