EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_network_synch.c Source File

thread_network_synch.c

00001 /*
00002  * Copyright (c) 2015-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 
00030 /*
00031  * \file thread_network_synch.c
00032  *
00033  */
00034 #include "nsconfig.h"
00035 #ifdef HAVE_THREAD
00036 #include <string.h>
00037 #include <ns_types.h>
00038 #include <nsdynmemLIB.h>
00039 #include "eventOS_event.h"
00040 #include "eventOS_event_timer.h"
00041 #include "randLIB.h"
00042 #include "common_functions.h"
00043 #include "NWK_INTERFACE/Include/protocol.h"
00044 #include "net_thread_test.h"
00045 #include "libDHCPv6/libDHCPv6.h"
00046 #include "libDHCPv6/libDHCPv6_server.h"
00047 #include "ns_trace.h"
00048 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00049 #include "6LoWPAN/Thread/thread_common.h"
00050 #include "6LoWPAN/Thread/thread_routing.h"
00051 #include "6LoWPAN/Thread/thread_nd.h"
00052 #include "6LoWPAN/Thread/thread_bootstrap.h"
00053 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00054 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00055 #include "6LoWPAN/Thread/thread_management_internal.h"
00056 #include "6LoWPAN/Thread/thread_joiner_application.h"
00057 #include "6LoWPAN/Thread/thread_management_client.h"
00058 #include "6LoWPAN/Thread/thread_network_synch.h"
00059 #include "thread_management_if.h"
00060 #include "thread_config.h"
00061 #include "Common_Protocols/ipv6.h"
00062 #include "Common_Protocols/icmpv6.h"
00063 #include "Common_Protocols/icmpv6_radv.h"
00064 #include "MLE/mle.h"
00065 #include "6LoWPAN/MAC/mac_helper.h"
00066 
00067 #define TRACE_GROUP "tsyn"
00068 
00069 typedef struct thread_sync_child_info {
00070     uint32_t mle_frame_counter;
00071     uint32_t mac_frame_counter;
00072     uint8_t long_addr[8];
00073     uint16_t short_addr;
00074     uint8_t mode;
00075 } thread_sync_child_info_t;
00076 
00077 typedef struct thread_network_dynamic_data_store {
00078     thread_leader_info_t *leader_private_data;
00079     thread_parent_info_t *thread_endnode_parent;
00080     thread_attach_state_e thread_attached_state;
00081     void *pending_configuration;
00082     uint64_t pending_timestamp;
00083     uint32_t mle_frame_counter;
00084     uint32_t mac_frame_counter;
00085     uint32_t network_sequence_counter;
00086     uint8_t  mleid[8];
00087     uint8_t  mac[8];
00088     uint16_t shortAddress;
00089     thread_sync_child_info_t children[THREAD_MAX_CHILD_COUNT];
00090 } thread_network_dynamic_data_store_t;
00091 
00092 
00093 typedef struct thread_network_dynamic_data_entry {
00094     int8_t interfaceId;
00095     ns_list_link_t link; /*!< List link entry */
00096     thread_network_dynamic_data_store_t networ_dynamic_data_parameters;
00097 } thread_network_dynamic_data_entry_t;
00098 
00099 static thread_sync_child_info_t *thread_dynamic_storage_free_child_find(int8_t interface_id);
00100 static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mle_neigh_table_entry_t *child);
00101 static NS_LIST_DEFINE(thread_network_dynamic_data_info, thread_network_dynamic_data_entry_t, link);
00102 
00103 thread_network_dynamic_data_entry_t *thread_network_synch_create(int8_t interfaceId)
00104 {
00105     thread_network_dynamic_data_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(thread_network_dynamic_data_entry_t));
00106     if (newEntry) {
00107         tr_debug("Allocate New Store");
00108         newEntry->interfaceId = interfaceId;
00109         newEntry->networ_dynamic_data_parameters.thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
00110         newEntry->networ_dynamic_data_parameters.shortAddress = 0xfffe;
00111         newEntry->networ_dynamic_data_parameters.leader_private_data = NULL;
00112         newEntry->networ_dynamic_data_parameters.thread_endnode_parent = NULL;
00113         newEntry->networ_dynamic_data_parameters.pending_configuration = NULL;
00114         newEntry->networ_dynamic_data_parameters.pending_timestamp = 0;
00115         newEntry->networ_dynamic_data_parameters.mac_frame_counter = 0;
00116         newEntry->networ_dynamic_data_parameters.mle_frame_counter = 0;
00117         newEntry->networ_dynamic_data_parameters.network_sequence_counter = 0;
00118         for (int i = 0; i < THREAD_MAX_CHILD_COUNT; ++i) {
00119             memset(&newEntry->networ_dynamic_data_parameters.children[i], 0, sizeof(thread_sync_child_info_t));
00120         }
00121         ns_list_add_to_end(&thread_network_dynamic_data_info, newEntry);
00122     }
00123     return newEntry;
00124 }
00125 
00126 thread_network_dynamic_data_entry_t *thread_network_synch_find(int8_t interfaceId)
00127 {
00128     //Check current  List
00129     ns_list_foreach(thread_network_dynamic_data_entry_t, cur, &thread_network_dynamic_data_info) {
00130         if (interfaceId == cur->interfaceId) {
00131             return cur;
00132         }
00133     }
00134     return NULL;
00135 }
00136 
00137 int thread_network_synch_delete(int8_t interfaceId)
00138 {
00139     thread_network_dynamic_data_entry_t *newEntry = thread_network_synch_find(interfaceId);
00140     if (newEntry) {
00141         //Free
00142         if (newEntry->networ_dynamic_data_parameters.leader_private_data) {
00143             ns_dyn_mem_free(newEntry->networ_dynamic_data_parameters.leader_private_data);
00144         }
00145 
00146         if (newEntry->networ_dynamic_data_parameters.thread_endnode_parent) {
00147             ns_dyn_mem_free(newEntry->networ_dynamic_data_parameters.thread_endnode_parent);
00148         }
00149 
00150         newEntry->networ_dynamic_data_parameters.thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
00151         newEntry->networ_dynamic_data_parameters.shortAddress = 0xfffe;
00152         newEntry->networ_dynamic_data_parameters.leader_private_data = NULL;
00153         newEntry->networ_dynamic_data_parameters.thread_endnode_parent = NULL;
00154 
00155         return 0;
00156     }
00157     return -1;
00158 }
00159 
00160 //Call This when clean synched networkdata
00161 int thread_network_synch_data_free(int8_t interface_id)
00162 {
00163     return thread_network_synch_delete(interface_id);
00164 }
00165 /*
00166  * Dynamic network data storage.
00167  */
00168 
00169 void thread_dynamic_storage_child_info_store(int8_t interface_id, mle_neigh_table_entry_t *child)
00170 {
00171     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00172 
00173     if (!storeEntry) {
00174         storeEntry = thread_network_synch_create(interface_id);
00175     }
00176 
00177     if (!storeEntry) {
00178         return;
00179     }
00180 
00181     thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(interface_id, child);
00182     if (child_info) {
00183         child_info->mode = child->mode;
00184         child_info->short_addr = child->short_adr;
00185         child_info->mle_frame_counter = child->mle_frame_counter;
00186         child_info->mac_frame_counter = 0;
00187         memcpy(child_info->long_addr, child->mac64, 8);
00188         return;
00189     }
00190 
00191     child_info = thread_dynamic_storage_free_child_find(interface_id);
00192 
00193     if (child_info) {
00194         child_info->mode = child->mode;
00195         child_info->short_addr = child->short_adr;
00196         child_info->mle_frame_counter = child->mle_frame_counter;
00197         child_info->mac_frame_counter = 0;
00198         memcpy(child_info->long_addr, child->mac64, 8);
00199     }
00200     return;
00201 }
00202 
00203 void thread_dynamic_storage_child_info_clear(int8_t interface_id, mle_neigh_table_entry_t *child)
00204 {
00205     thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(interface_id, child);
00206 
00207     if (child_info){
00208         // Clear child information
00209         memset (child_info,0,sizeof(thread_sync_child_info_t));
00210         tr_debug("Dynamic storage: cleared child; mac16=%04x", child->short_adr);
00211         return;
00212     }
00213     return;
00214 }
00215 
00216 static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mle_neigh_table_entry_t *child)
00217 {
00218     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00219 
00220     if (!storeEntry) {
00221         return NULL;
00222     }
00223 
00224     for (uint16_t i = 0; i < THREAD_MAX_CHILD_COUNT; ++i) {
00225         uint8_t *mac64 = storeEntry->networ_dynamic_data_parameters.children[i].long_addr;
00226         if (memcmp(mac64, child->mac64, 8) == 0) {
00227             return &storeEntry->networ_dynamic_data_parameters.children[i];
00228         }
00229     }
00230     return NULL;
00231 }
00232 
00233 static thread_sync_child_info_t *thread_dynamic_storage_free_child_find(int8_t interface_id)
00234 {
00235     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00236     if (!storeEntry) {
00237         return NULL;
00238     }
00239     for (int i = 0; i < THREAD_MAX_CHILD_COUNT; ++i) {
00240         if (storeEntry->networ_dynamic_data_parameters.children[i].short_addr == 0) {
00241             return &storeEntry->networ_dynamic_data_parameters.children[i];
00242         }
00243     }
00244     return NULL;
00245 }
00246 
00247 void thread_dynamic_storage_build_mle_table(int8_t interface_id)
00248 {
00249     tr_debug("Dynamic storage: building MLE table.");
00250 
00251     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00252 
00253     if (!storeEntry) {
00254         storeEntry = thread_network_synch_create(interface_id);
00255     }
00256 
00257     if (!storeEntry) {
00258         return;
00259     }
00260 
00261     mle_neigh_table_list_t *neig_list = mle_class_active_list_get(interface_id);
00262 
00263     if (!neig_list) {
00264         return;
00265     }
00266 
00267     int i;
00268     for (i = 0; i < THREAD_MAX_CHILD_COUNT; ++i) {
00269         if (storeEntry->networ_dynamic_data_parameters.children[i].short_addr == 0) {
00270             // Skip empty child entry
00271             continue;
00272         }
00273         uint8_t *mac64 = storeEntry->networ_dynamic_data_parameters.children[i].long_addr;
00274         tr_debug("Child: %04x, %s", storeEntry->networ_dynamic_data_parameters.children[i].short_addr, trace_array(mac64, 8));
00275         mle_neigh_table_entry_t *entry = mle_class_get_entry_by_mac64(interface_id, 64, mac64, true);
00276         if (entry) {
00277             entry->short_adr = storeEntry->networ_dynamic_data_parameters.children[i].short_addr;
00278             entry->mle_frame_counter = storeEntry->networ_dynamic_data_parameters.children[i].mle_frame_counter;
00279             entry->mode = storeEntry->networ_dynamic_data_parameters.children[i].mode;
00280             entry->threadNeighbor = true;
00281 
00282             protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00283 
00284             if (cur && cur->mac_parameters) {
00285                 // Set MAC layer frame counter for the child
00286                 mac_helper_devicetable_set(entry, cur, storeEntry->networ_dynamic_data_parameters.children[i].mac_frame_counter, cur->mac_parameters->mac_default_key_index);
00287             }
00288         }
00289     }
00290 }
00291 
00292 
00293 
00294 /*Pending configuration storage*/
00295 void thread_dynamic_storage_pending_configuration_store(int8_t interface_id, void *data, uint16_t size)
00296 {
00297     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00298     if (!storeEntry) {
00299         storeEntry = thread_network_synch_create(interface_id);
00300     }
00301     if (!storeEntry) {
00302         return;
00303     }
00304 
00305     tr_info("saved pending configuration to store");
00306     ns_dyn_mem_free(storeEntry->networ_dynamic_data_parameters.pending_configuration);
00307     storeEntry->networ_dynamic_data_parameters.pending_configuration = NULL;
00308     if (!data || !size) {
00309         return;
00310     }
00311 
00312     storeEntry->networ_dynamic_data_parameters.pending_configuration = ns_dyn_mem_alloc(size);
00313     if (!storeEntry->networ_dynamic_data_parameters.pending_configuration) {
00314         return;
00315     }
00316     memcpy(storeEntry->networ_dynamic_data_parameters.pending_configuration, data,size);
00317 
00318 }
00319 
00320 bool thread_dynamic_storage_pending_configuration_exists(int8_t interface_id)
00321 {
00322     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00323     if (!storeEntry || !storeEntry->networ_dynamic_data_parameters.pending_configuration) {
00324         tr_debug("no pending config found in store");
00325         return false;
00326     }
00327     return true;
00328 }
00329 void thread_dynamic_storage_pending_configuration_read(int8_t interface_id, void *data, uint16_t size)
00330 {
00331     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00332     if (!storeEntry || !storeEntry->networ_dynamic_data_parameters.pending_configuration) {
00333         tr_debug("no pending config found in store");
00334         return;
00335     }
00336     memcpy(data,storeEntry->networ_dynamic_data_parameters.pending_configuration, size);
00337     return;
00338 }
00339 
00340 int thread_pending_data_delete(int8_t interfaceId)
00341 {
00342     thread_network_dynamic_data_entry_t *newEntry = thread_network_synch_find(interfaceId);
00343     if (newEntry) {
00344       //Free
00345         newEntry->networ_dynamic_data_parameters.pending_configuration = NULL;
00346         newEntry->networ_dynamic_data_parameters.pending_timestamp = 0;
00347         return 0;
00348     }
00349     return -1;
00350 }
00351 
00352 void thread_dynamic_storage_device_configuration_read(int8_t interface_id, uint8_t *mac_ptr, uint8_t *mleid_ptr)
00353 {
00354     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00355     if (!storeEntry) {
00356         tr_error("no device configuration in store");
00357         return;
00358     }
00359     memcpy(mac_ptr,storeEntry->networ_dynamic_data_parameters.mac, 8);
00360     memcpy(mleid_ptr,storeEntry->networ_dynamic_data_parameters.mleid, 8);
00361     return;
00362 }
00363 
00364 void thread_dynamic_storage_device_configuration_store(int8_t interface_id, uint8_t *mac_ptr, uint8_t *mleid_ptr)
00365 {
00366     thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
00367     if (!storeEntry) {
00368         storeEntry = thread_network_synch_create(interface_id);
00369     }
00370     if (!storeEntry) {
00371         return;
00372     }
00373     tr_debug("store device configuration");
00374     memcpy(storeEntry->networ_dynamic_data_parameters.mac, mac_ptr, 8);
00375     memcpy(storeEntry->networ_dynamic_data_parameters.mleid,mleid_ptr, 8);
00376     return;
00377 }
00378 
00379 static uint8_t loaded = false;
00380 static uint8_t mac[8] = {0};
00381 static uint16_t short_addr = 0xffff;
00382 
00383 void thread_nvm_store_link_info_file_read()
00384 {
00385     if (!memcmp(mac,ADDR_UNSPECIFIED,8) && short_addr == 0xffff) {
00386         return;
00387     }
00388     // File exists at bootup
00389     loaded = true;
00390 }
00391 bool thread_nvm_store_link_info_get(uint8_t *parent_mac64, uint16_t *my_short_address)
00392 {
00393     if (!memcmp(mac,ADDR_UNSPECIFIED,8) && short_addr == 0xffff) {
00394         return false;
00395     }
00396     if (!loaded) {
00397         return false;
00398     }
00399     if (parent_mac64) {
00400         memcpy(parent_mac64,mac,8);
00401     }
00402     if (my_short_address) {
00403         *my_short_address = short_addr;
00404     }
00405 
00406     // File was found and values read
00407     return true;
00408 }
00409 
00410 void thread_nvm_store_link_info_clear()
00411 {
00412     memset(mac,0,8);
00413     short_addr = 0xffff;
00414     loaded = false;
00415     // synchronised settings were used and now are deleted
00416     // it is only allowed to use synch settings during the first boot
00417 }
00418 
00419 void thread_nvm_store_link_info_file_write(protocol_interface_info_entry_t *cur)
00420 {
00421     if(cur->thread_info->thread_endnode_parent) {
00422         memcpy(mac,cur->thread_info->thread_endnode_parent->mac64,8);
00423     } else {
00424         memset(mac,0,8);
00425     }
00426     short_addr = mac_helper_mac16_address_get(cur);
00427     // Settings are changed, but values should not be saved yet only after certain
00428     // grace period. But the values are not returned in get.
00429 }
00430 #endif