takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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