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