Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
thread_network_data_storage.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 00030 /* 00031 * \file thread_network_data_storage.c 00032 * \brief Add short description about this file!!! 00033 * 00034 */ 00035 00036 #include "nsconfig.h" 00037 #ifdef HAVE_THREAD 00038 #include <string.h> 00039 #include <ns_types.h> 00040 #include <nsdynmemLIB.h> 00041 #include "NWK_INTERFACE/Include/protocol.h" 00042 #include "common_functions.h" 00043 #include "ns_trace.h" 00044 #include "ip6string.h" 00045 #include "6LoWPAN/Thread/thread_common.h" 00046 #include "6LoWPAN/Thread/thread_config.h" 00047 #include "6LoWPAN/Thread/thread_extension.h" 00048 #include "6LoWPAN/Thread/thread_joiner_application.h" 00049 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00050 #include "6LoWPAN/Thread/thread_network_data_storage.h" 00051 #include "6LoWPAN/Thread/thread_dhcpv6_client.h" 00052 #include "6LoWPAN/MAC/mac_helper.h" 00053 #include "thread_management_if.h" 00054 #include "thread_meshcop_lib.h" 00055 #include "libDHCPv6/libDHCPv6_server.h" 00056 #include "DHCPv6_Server/DHCPv6_server_service.h" 00057 00058 #define TRACE_GROUP "thrd" 00059 00060 00061 static void network_server_print(const thread_network_server_data_entry_t *route) 00062 { 00063 #ifndef HAVE_DEBUG 00064 (void) route; 00065 #endif 00066 00067 tr_info("%s Info: routerId:%04x", 00068 (route->stableData ? "Stable" : "Temporary"), 00069 route->routerID); 00070 } 00071 00072 //@TODO seems that this function is called from application, 00073 // is there better way than print data inside stack ? 00074 void thread_nd_network_data_print(thread_network_data_cache_entry_t *networkData, uint16_t routerId) 00075 { 00076 // Route prefix is variable-length, so need to zero pad for ip6tos 00077 uint8_t addr[16]; 00078 tr_info("Network Data:"); 00079 00080 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkData->localPrefixList ) { 00081 memset(addr, 0, 16); 00082 bitcopy(addr, cur->servicesPrefix, cur->servicesPrefixLen); 00083 tr_info("Prefix: %40s/%-3u", trace_ipv6(addr), cur->servicesPrefixLen); 00084 ns_list_foreach(thread_network_server_data_entry_t, curRoute, &cur->routeList) { 00085 tr_info("Has Route:"); 00086 if (curRoute->routerID != routerId) { 00087 network_server_print(curRoute); 00088 } else { 00089 tr_info("This Interface"); 00090 } 00091 } 00092 00093 ns_list_foreach(thread_network_server_data_entry_t, curRoute, &cur->borderRouterList) { 00094 if (curRoute->P_dhcp) { 00095 tr_info("DHCPv6:"); 00096 } 00097 if (curRoute->P_slaac || curRoute->P_preferred) { 00098 tr_info("SLAAC:"); 00099 } 00100 if (curRoute->routerID != routerId) { 00101 network_server_print(curRoute); 00102 } else { 00103 tr_info("I'm Hosting"); 00104 } 00105 } 00106 } 00107 } 00108 00109 uint8_t thread_nd_server_external_route_list_size(thread_network_server_data_list_t *list, bool stable) 00110 { 00111 00112 uint8_t listSize = 0; 00113 00114 ns_list_foreach(thread_network_server_data_entry_t, cur, list) { 00115 if (cur->stableData == stable) { 00116 listSize += 3; 00117 } 00118 } 00119 00120 if (listSize) { 00121 listSize += 2; 00122 } 00123 00124 return listSize; 00125 } 00126 00127 uint8_t thread_nd_border_routerserver_list_size(thread_network_server_data_list_t *list, bool stable) 00128 { 00129 uint8_t listSize = 0; 00130 00131 ns_list_foreach(thread_network_server_data_entry_t, cur, list) { 00132 if (cur->stableData == stable) { 00133 listSize += 4; 00134 } 00135 } 00136 if (listSize) { 00137 listSize += 2; 00138 } 00139 00140 return listSize; 00141 } 00142 00143 uint8_t thread_nd_context_list_size(thread_data_context_list_t *list, bool stable) 00144 { 00145 uint8_t listSize = 0; 00146 00147 ns_list_foreach(thread_network_data_context_entry_t, cur, list) { 00148 if (cur->stableData == stable) { 00149 listSize += 2; 00150 } 00151 } 00152 00153 if (listSize) { 00154 listSize += 2; 00155 } 00156 return listSize; 00157 } 00158 00159 uint8_t *thread_nd_context_list_write(thread_data_context_list_t *list, uint8_t *dataPtr, bool stableData) 00160 { 00161 uint8_t tlv_size = 0; 00162 uint8_t *ptr = (dataPtr + 2); //Leave allways Type & Length free first 00163 00164 ns_list_foreach(thread_network_data_context_entry_t, cur, list) { 00165 if (cur->stableData == stableData) { 00166 tlv_size += 2; 00167 *ptr++ = cur->cid | (cur->compression ? THREAD_NWK_CONTEXT_COMPRESS_ENABLED : 0); 00168 *ptr++ = cur->contextPrefixLength; 00169 } 00170 } 00171 if (tlv_size) { 00172 uint8_t type = THREAD_NWK_DATA_TYPE_6LOWPAN_ID; 00173 if (stableData) { 00174 type |= THREAD_NWK_STABLE_DATA; 00175 } 00176 00177 *dataPtr++ = type; 00178 *dataPtr = tlv_size; 00179 //SET Pointer back to end of data 00180 dataPtr = ptr; 00181 } 00182 00183 return dataPtr; 00184 } 00185 00186 static uint16_t thread_nd_service_border_router_flags_read(thread_network_server_data_entry_t *cur) 00187 { 00188 uint16_t flags = (cur->Prf << THREAD_PRF_BIT_MOVE); 00189 flags |= (cur->P_preferred << THREAD_P_PREFERRED_BIT_MOVE); 00190 flags |= (cur->P_slaac << THREAD_P_SLAAC_BIT_MOVE); 00191 flags |= (cur->P_dhcp << THREAD_P_DHCP_BIT_MOVE); 00192 flags |= (cur->P_configure << THREAD_P_CONFIGURE_BIT_MOVE); 00193 flags |= (cur->P_default_route << THREAD_P_DEF_ROUTE_BIT_MOVE); 00194 flags |= (cur->P_on_mesh << THREAD_P_ON_MESH_BIT_MOVE); 00195 flags |= (cur->P_nd_dns << THREAD_P_ND_DNS_BIT_MOVE); 00196 return flags; 00197 } 00198 00199 uint8_t *thread_nd_server_list_write(thread_network_server_data_list_t *list, uint8_t *dataPtr, uint8_t type, bool stable) 00200 { 00201 uint8_t tlv_size = 0, tlv_length; 00202 uint16_t flags; 00203 uint8_t *ptr = (dataPtr + 2); //Leave allways Type & Length free first 00204 uint16_t routerId; 00205 00206 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 00207 tlv_length = THREAD_BORDER_ROUTER_TLV_LENGTH; 00208 } else { 00209 tlv_length = THREAD_HAS_ROUTE_TLV_LENGTH; 00210 } 00211 00212 ns_list_foreach(thread_network_server_data_entry_t, cur, list) { 00213 if (cur->stableData == stable) { 00214 tlv_size += tlv_length; 00215 routerId = cur->routerID; 00216 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 00217 flags = thread_nd_service_border_router_flags_read(cur); 00218 ptr = thread_nd_network_data_border_router_tlv_write(ptr, routerId, flags); 00219 } else { 00220 uint8_t pref = (cur->Prf << THREAD_HAS_ROUTE_PRF_BIT_MOVE); 00221 ptr = thread_nd_network_data_has_route_tlv_write(ptr, routerId, pref); 00222 } 00223 } 00224 } 00225 00226 if (tlv_size) { 00227 if (stable) { 00228 type |= THREAD_NWK_STABLE_DATA; 00229 } 00230 *dataPtr++ = type; 00231 *dataPtr = tlv_size; 00232 //SET Pointer back to end of data 00233 dataPtr = ptr; 00234 } 00235 00236 return dataPtr; 00237 } 00238 00239 uint8_t *thread_nd_service_server_list_write(thread_network_data_service_server_list_t *list, uint8_t *ptr, bool full_list) 00240 { 00241 ns_list_foreach(thread_network_data_service_server_entry_t, cur, list) { 00242 if (!full_list && !cur->stable) { 00243 continue; 00244 } 00245 00246 if (cur->stable) { 00247 *ptr++ = THREAD_NWK_DATA_TYPE_SERVER_DATA | THREAD_NWK_STABLE_DATA; 00248 } else { 00249 *ptr++ = THREAD_NWK_DATA_TYPE_SERVER_DATA; 00250 } 00251 00252 *ptr++ = 2 + cur->server_data_length; 00253 ptr = common_write_16_bit(cur->router_id, ptr); 00254 00255 memcpy(ptr, cur->server_data, cur->server_data_length); 00256 ptr += cur->server_data_length; 00257 } 00258 00259 return ptr; 00260 } 00261 00262 uint8_t thread_nd_service_based_on_list_entry_size(thread_network_data_service_cache_entry_t *entry, bool fullList) 00263 { 00264 uint8_t tempTlvSize = 0; 00265 00266 ns_list_foreach(thread_network_data_service_server_entry_t, cur, &entry->server_list) { 00267 if (!fullList && !cur->stable) { 00268 continue; 00269 } 00270 tempTlvSize += 4; // Type, Length, and S_server_16 00271 tempTlvSize += cur->server_data_length; 00272 } 00273 00274 if (tempTlvSize) { 00275 tempTlvSize += 2; // T + S_id + service data length 00276 00277 if (!entry->T) { 00278 tempTlvSize += 4; 00279 } 00280 00281 tempTlvSize += entry->S_service_data_length; 00282 } 00283 00284 return tempTlvSize; 00285 } 00286 00287 uint8_t thread_nd_prefix_based_on_list_entry_size(thread_network_data_prefix_cache_entry_t *entry, bool fullList) 00288 { 00289 uint8_t tempTlvSize = 0; 00290 00291 tempTlvSize += thread_nd_border_routerserver_list_size(&entry->borderRouterList, true); 00292 tempTlvSize += thread_nd_server_external_route_list_size(&entry->routeList, true); 00293 tempTlvSize += thread_nd_context_list_size(&entry->contextList, true); 00294 if (fullList) { 00295 tempTlvSize += thread_nd_border_routerserver_list_size(&entry->borderRouterList, false); 00296 tempTlvSize += thread_nd_server_external_route_list_size(&entry->routeList, false); 00297 tempTlvSize += thread_nd_context_list_size(&entry->contextList, false); 00298 } 00299 00300 if (tempTlvSize) { 00301 tempTlvSize += prefixBits_to_bytes(entry->servicesPrefixLen ); 00302 tempTlvSize += 2; //Domain ID & Length 00303 } 00304 return tempTlvSize; 00305 } 00306 00307 int thread_nd_local_data_length_updated(thread_network_data_cache_entry_t *networkDataList) 00308 { 00309 int ret_val = -1; 00310 uint16_t localDataLength = 0; 00311 localDataLength = thread_network_data_prefix_set_size(networkDataList, true) 00312 + thread_network_data_service_set_size(networkDataList, true); 00313 00314 if (localDataLength != networkDataList->networkDataTlvSize ) { 00315 networkDataList->networkDataTlvSize = localDataLength; 00316 ret_val = 0; 00317 } 00318 return ret_val; 00319 } 00320 00321 00322 thread_network_local_data_entry_t *thread_local_service_list_allocate(thread_prefix_tlv_t *prefixTlv) 00323 { 00324 thread_network_local_data_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(thread_network_local_data_entry_t)); 00325 if (newEntry) { 00326 memset(newEntry->servicesPrefix, 0, 16); 00327 bitcopy(newEntry->servicesPrefix, prefixTlv->Prefix, prefixTlv->PrefixLen); 00328 newEntry->servicesPrefixLen = prefixTlv->PrefixLen; 00329 newEntry->domainId = prefixTlv->domainId; 00330 newEntry->dhcpv6ServerActive = false; 00331 newEntry->dhcpv6ServerDataStable = false; 00332 newEntry->slaacServerActive = false; 00333 newEntry->slaacServerDataStable = false; 00334 newEntry->slaacPreferred = false; 00335 newEntry->routeActive = false; 00336 newEntry->routeDataStable = false; 00337 newEntry->preference = 0; 00338 newEntry->configure = false; 00339 newEntry->defaultRoute = false; 00340 newEntry->onMesh = false; 00341 newEntry->ndDns = false; 00342 } 00343 return newEntry; 00344 } 00345 00346 thread_network_data_prefix_cache_entry_t *thread_prefix_service_list_allocate(thread_prefix_tlv_t *prefixTlv) 00347 { 00348 thread_network_data_prefix_cache_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(thread_network_data_prefix_cache_entry_t)); 00349 if (newEntry) { 00350 memset(newEntry->servicesPrefix , 0, 16); 00351 bitcopy(newEntry->servicesPrefix , prefixTlv->Prefix, prefixTlv->PrefixLen); 00352 newEntry->servicesPrefixLen = prefixTlv->PrefixLen; 00353 newEntry->domainId = prefixTlv->domainId; 00354 ns_list_init(&newEntry->contextList); 00355 ns_list_init(&newEntry->borderRouterList); 00356 ns_list_init(&newEntry->routeList); 00357 } 00358 return newEntry; 00359 } 00360 00361 thread_network_server_data_entry_t *thread_server_entry_allocate(thread_border_router_tlv_entry_t *service) 00362 { 00363 thread_network_server_data_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(thread_network_server_data_entry_t)); 00364 if (newEntry) { 00365 tr_debug("Create new server entry addr: %04x",service->routerID); 00366 newEntry->routerID = service->routerID; 00367 newEntry->stableData = service->stableData; 00368 newEntry->P_configure = service->P_configure; 00369 newEntry->P_default_route = service->P_default_route; 00370 newEntry->P_dhcp = service->P_dhcp; 00371 newEntry->P_preferred = service->P_preferred; 00372 newEntry->P_slaac = service->P_slaac; 00373 newEntry->Prf = service->Prf; 00374 newEntry->P_on_mesh = service->P_on_mesh; 00375 newEntry->P_nd_dns = service->P_nd_dns; 00376 newEntry->canDelete = false; 00377 00378 } 00379 return newEntry; 00380 } 00381 00382 thread_network_data_context_entry_t *thread_context_service_list_allocate(uint8_t contextLength, uint8_t cid, bool compersioEnabled) 00383 { 00384 thread_network_data_context_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(thread_network_data_context_entry_t)); 00385 if (newEntry) { 00386 newEntry->cid = cid; 00387 newEntry->compression = compersioEnabled; 00388 newEntry->contextPrefixLength = contextLength; 00389 newEntry->canDelete = false; 00390 newEntry->stableData = false; 00391 } 00392 return newEntry; 00393 } 00394 00395 int thread_nd_verify_contex_id_is_free(thread_network_data_cache_entry_t *list, uint8_t *prefixPtr, thread_network_local_data_context_entry_t *context) 00396 { 00397 int retVal = 0; 00398 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &list->localPrefixList ) { 00399 00400 ns_list_foreach(thread_network_data_context_entry_t, curContetx, &cur->contextList) { 00401 if (curContetx->cid == context->cid) { 00402 if (context->contextPrefixLength == cur->servicesPrefixLen) { 00403 if (!bitsequal(cur->servicesPrefix, prefixPtr, context->contextPrefixLength)) { 00404 retVal = -1; //Do not accept same context anymore again if prefix is different 00405 } 00406 } else { 00407 retVal = -1; 00408 } 00409 00410 return retVal; 00411 } 00412 } 00413 00414 } 00415 return retVal; 00416 } 00417 00418 thread_network_data_service_cache_entry_t *thread_network_data_service_entry_find(thread_network_data_service_cache_list_t *list, thread_network_data_service_entry_t *service) 00419 { 00420 ns_list_foreach(thread_network_data_service_cache_entry_t, cur, list) { 00421 if (service->S_enterprise_number == cur->S_enterprise_number) { 00422 if (service->S_service_data_length == cur->S_service_data_length) { 00423 if (memcmp(service->S_service_data, cur->S_service_data, service->S_service_data_length) == 0) { 00424 return cur; 00425 } 00426 } 00427 } 00428 } 00429 00430 return NULL; 00431 } 00432 00433 thread_network_data_service_entry_t *thread_local_service_entry_find(thread_network_data_service_list_t *list, thread_network_data_service_entry_t *service) 00434 { 00435 ns_list_foreach(thread_network_data_service_entry_t, cur, list) { 00436 if (service->S_enterprise_number == cur->S_enterprise_number) { 00437 if (service->S_service_data_length == cur->S_service_data_length) { 00438 if (memcmp(service->S_service_data, cur->S_service_data, service->S_service_data_length) == 0) { 00439 return cur; 00440 } 00441 } 00442 } 00443 } 00444 00445 return NULL; 00446 } 00447 00448 thread_network_data_service_entry_t *thread_local_service_entry_save(thread_network_data_service_list_t *list, thread_network_data_service_entry_t *service) 00449 { 00450 thread_network_data_service_entry_t *service_entry; 00451 service_entry = thread_local_service_entry_find(list, service); 00452 00453 if (service_entry) { 00454 service_entry->S_id = service->S_id; 00455 service_entry->S_stable = service->S_stable; 00456 00457 if (service_entry->S_server_data) { 00458 ns_dyn_mem_free(service_entry->S_server_data); 00459 service_entry->S_server_data = NULL; 00460 } 00461 00462 if (service->S_server_data_length) { 00463 service_entry->S_server_data = ns_dyn_mem_alloc(service->S_server_data_length); 00464 } 00465 00466 if (service_entry->S_server_data) { 00467 service_entry->S_server_data_length = service->S_server_data_length; 00468 memcpy(service_entry->S_server_data, service->S_server_data, service->S_server_data_length); 00469 } 00470 00471 return service_entry; 00472 } 00473 00474 service_entry = ns_dyn_mem_alloc(sizeof(thread_network_data_service_entry_t)); 00475 00476 if (service_entry) { 00477 memset(service_entry, 0, sizeof(thread_network_data_service_entry_t)); 00478 00479 service_entry->T = service->T; 00480 service_entry->S_id = service->S_id; 00481 service_entry->S_stable = service->S_stable; 00482 service_entry->S_enterprise_number = service->S_enterprise_number; 00483 service_entry->S_service_data = ns_dyn_mem_alloc(service->S_service_data_length); 00484 00485 if (!service_entry->S_service_data) { 00486 tr_error("Failed to allocate memory for service data!"); 00487 ns_dyn_mem_free(service_entry); 00488 return NULL; 00489 } 00490 00491 service_entry->S_service_data_length = service->S_service_data_length; 00492 memcpy(service_entry->S_service_data, service->S_service_data, service->S_service_data_length); 00493 00494 if (service->S_server_data_length) { 00495 service_entry->S_server_data = ns_dyn_mem_alloc(service->S_server_data_length); 00496 00497 if (!service_entry->S_server_data) { 00498 tr_error("Failed to allocate memory for server data!"); 00499 ns_dyn_mem_free(service_entry->S_service_data); 00500 ns_dyn_mem_free(service_entry); 00501 return NULL; 00502 } 00503 00504 service_entry->S_server_data_length = service->S_server_data_length; 00505 memcpy(service_entry->S_server_data, service->S_server_data, service->S_server_data_length); 00506 } 00507 00508 ns_list_add_to_end(list, service_entry); 00509 00510 tr_debug("Added service; enterprise number: %"PRIu32", service: %s", service_entry->S_enterprise_number, 00511 trace_array(service_entry->S_service_data, service_entry->S_service_data_length)); 00512 } 00513 00514 return service_entry; 00515 } 00516 00517 thread_network_local_data_entry_t *thread_local_prefix_entry_find(thread_network_data_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv) 00518 { 00519 ns_list_foreach(thread_network_local_data_entry_t, cur, list) { 00520 if (prefixTlv->domainId == cur->domainId) { 00521 if (prefixTlv->PrefixLen == cur->servicesPrefixLen) { 00522 if (bitsequal(cur->servicesPrefix, prefixTlv->Prefix, prefixTlv->PrefixLen)) { 00523 return cur; 00524 } 00525 } 00526 } 00527 } 00528 return NULL; 00529 } 00530 00531 thread_network_local_data_entry_t *thread_local_prefix_entry_get(thread_network_data_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv) 00532 { 00533 thread_network_local_data_entry_t *prefix_entry; 00534 00535 //Check current Prefix List 00536 prefix_entry = thread_local_prefix_entry_find(list, prefixTlv); 00537 if (prefix_entry) { 00538 return prefix_entry; 00539 } 00540 00541 prefix_entry = thread_local_service_list_allocate(prefixTlv); 00542 if (prefix_entry) { 00543 bool inserted = false; 00544 ns_list_foreach(thread_network_local_data_entry_t, cur, list) { 00545 if (prefixTlv->PrefixLen >= cur->servicesPrefixLen) { //Add always longer or same length to before last one 00546 //add before new 00547 tr_debug("Add new Longer"); 00548 inserted = true; 00549 ns_list_add_before(list, cur, prefix_entry); 00550 break; 00551 } 00552 } 00553 if (!inserted) { 00554 tr_debug("Add to end"); 00555 ns_list_add_to_end(list, prefix_entry); 00556 } 00557 } 00558 return prefix_entry; 00559 } 00560 00561 uint8_t thread_service_next_free_service_type_id(thread_network_data_service_cache_list_t *list) 00562 { 00563 uint8_t sid; 00564 00565 for (sid = 0; sid < 16; ++sid) { 00566 bool found = false; 00567 00568 ns_list_foreach(thread_network_data_service_cache_entry_t, cur, list) { 00569 if (cur->S_id == sid) { 00570 found = true; 00571 break; 00572 } 00573 } 00574 00575 if (!found) { 00576 return sid; 00577 } 00578 } 00579 00580 return 0xff; // IDs exhausted 00581 } 00582 00583 thread_network_data_prefix_cache_entry_t *thread_prefix_entry_find(thread_network_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv) 00584 { 00585 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, list) { 00586 if (prefixTlv->domainId == cur->domainId) { 00587 if (prefixTlv->PrefixLen == cur->servicesPrefixLen) { 00588 if (bitsequal(cur->servicesPrefix, prefixTlv->Prefix, prefixTlv->PrefixLen)) { 00589 return cur; 00590 } 00591 } 00592 } 00593 } 00594 return NULL; 00595 } 00596 thread_network_data_prefix_cache_entry_t *thread_prefix_entry_get(thread_network_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv) 00597 { 00598 thread_network_data_prefix_cache_entry_t *main_list; 00599 //Check current Prefix List 00600 main_list = thread_prefix_entry_find(list, prefixTlv); 00601 if (main_list) { 00602 return main_list; 00603 } 00604 00605 main_list = thread_prefix_service_list_allocate(prefixTlv); 00606 tr_info("New prefix added"); 00607 00608 if (main_list) { 00609 bool inserted = false; 00610 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, list) { 00611 if (prefixTlv->PrefixLen >= cur->servicesPrefixLen) { //Add always longer or same length to before last one 00612 //add before new 00613 tr_debug("Add new Longer"); 00614 inserted = true; 00615 ns_list_add_before(list, cur, main_list); 00616 break; 00617 } 00618 } 00619 if (!inserted) { 00620 tr_debug("Add to end"); 00621 ns_list_add_to_end(list, main_list); 00622 } 00623 } 00624 00625 return main_list; 00626 } 00627 00628 thread_network_data_service_cache_entry_t *thread_service_entry_get(thread_network_data_service_cache_list_t *list, thread_network_data_service_entry_t *service) 00629 { 00630 thread_network_data_service_cache_entry_t *service_entry; 00631 00632 service_entry = thread_network_data_service_entry_find(list, service); 00633 00634 if (service_entry) { 00635 return service_entry; 00636 } 00637 00638 service_entry = ns_dyn_mem_alloc(sizeof(thread_network_data_service_cache_entry_t)); 00639 00640 if (service_entry) { 00641 memset(service_entry, 0, sizeof(thread_network_data_service_entry_t)); 00642 00643 service_entry->T = service->T; 00644 service_entry->S_stable = service->S_stable; 00645 service_entry->S_enterprise_number = service->S_enterprise_number; 00646 00647 uint8_t sid = thread_service_next_free_service_type_id(list); 00648 00649 if (sid == 0xff) { 00650 tr_error("All Service Type ID (S_id) values used!"); 00651 ns_dyn_mem_free(service_entry); 00652 return NULL; 00653 } 00654 00655 service_entry->S_id = sid; 00656 service_entry->S_service_data = ns_dyn_mem_alloc(service->S_service_data_length); 00657 00658 if (!service_entry->S_service_data) { 00659 tr_error("Failed to allocate memory for service data!"); 00660 ns_dyn_mem_free(service_entry); 00661 return NULL; 00662 } 00663 00664 service_entry->S_service_data_length = service->S_service_data_length; 00665 memcpy(service_entry->S_service_data, service->S_service_data, service->S_service_data_length); 00666 ns_list_init(&service_entry->server_list); 00667 ns_list_add_to_end(list, service_entry); 00668 } 00669 00670 return service_entry; 00671 } 00672 00673 thread_network_server_data_entry_t *thread_server_entry_search(thread_network_server_data_list_t *list, uint16_t routerId) 00674 { 00675 ns_list_foreach(thread_network_server_data_entry_t, cur, list) { 00676 if (cur->routerID == routerId) { 00677 cur->canDelete = false; 00678 return cur; 00679 } 00680 } 00681 return NULL; 00682 } 00683 00684 thread_network_data_service_server_entry_t *thread_service_server_entry_search(thread_network_data_service_server_list_t *list, uint16_t routerId) 00685 { 00686 ns_list_foreach(thread_network_data_service_server_entry_t, cur, list) { 00687 if (cur->router_id == routerId) { 00688 cur->can_delete = false; 00689 return cur; 00690 } 00691 } 00692 return NULL; 00693 } 00694 00695 thread_network_server_data_entry_t *thread_server_entry_get(thread_network_server_data_list_t *list, thread_border_router_tlv_entry_t *service) 00696 { 00697 thread_network_server_data_entry_t *server_entry; 00698 bool inserted = false; 00699 00700 //Check current Stable List 00701 server_entry = thread_server_entry_search(list, service->routerID); 00702 if (server_entry) { 00703 return server_entry; 00704 } 00705 server_entry = thread_server_entry_allocate(service); 00706 if (!server_entry) { 00707 return NULL; 00708 } 00709 tr_info("New server entry made"); 00710 ns_list_foreach(thread_network_server_data_entry_t, cur, list) 00711 { 00712 if (service->routerID < cur->routerID) { //Add always longer or same length to before last one 00713 //add before new 00714 tr_debug("Add smaller id"); 00715 inserted = true; 00716 ns_list_add_before(list, cur, server_entry); 00717 break; 00718 } 00719 } 00720 if (!inserted) { 00721 tr_debug("Add new Last"); 00722 ns_list_add_to_end(list, server_entry); 00723 } 00724 00725 return server_entry; 00726 } 00727 00728 thread_network_data_service_server_entry_t *thread_service_server_entry_get(thread_network_data_service_server_list_t *list, thread_network_data_service_server_entry_t *server) 00729 { 00730 thread_network_data_service_server_entry_t *server_entry; 00731 00732 server_entry = thread_service_server_entry_search(list, server->router_id); 00733 00734 if (server_entry) { 00735 return server_entry; 00736 } 00737 00738 server_entry = ns_dyn_mem_alloc(sizeof(thread_network_data_service_server_entry_t)); 00739 00740 if (server_entry) { 00741 memset(server_entry, 0, sizeof(thread_network_data_service_server_entry_t)); 00742 00743 server_entry->can_delete = false; 00744 server_entry->router_id = server->router_id; 00745 server_entry->stable = server->stable; 00746 server_entry->server_data = ns_dyn_mem_alloc(server->server_data_length); 00747 00748 if (!server_entry->server_data) { 00749 tr_error("Failed to allocate memory for server data!"); 00750 ns_dyn_mem_free(server_entry); 00751 return NULL; 00752 } 00753 00754 server_entry->server_data_length = server->server_data_length; 00755 memcpy(server_entry->server_data, server->server_data, server->server_data_length); 00756 ns_list_add_to_end(list, server_entry); 00757 } 00758 00759 return server_entry; 00760 } 00761 00762 uint8_t thread_get_context_id_by_length(thread_data_context_list_t *list, uint8_t contextLength) 00763 { 00764 //Check current Stable List 00765 ns_list_foreach(thread_network_data_context_entry_t, cur, list) { 00766 if (cur->contextPrefixLength == contextLength) { 00767 return cur->cid; 00768 } 00769 } 00770 return 16; 00771 } 00772 00773 thread_network_data_context_entry_t *thread_get_context_by_id(thread_data_context_list_t *list, uint8_t cid) 00774 { 00775 //Check current Stable List 00776 ns_list_foreach(thread_network_data_context_entry_t, cur, list) { 00777 if (cur->cid == cid) { 00778 return cur; 00779 } 00780 } 00781 return NULL; 00782 } 00783 00784 thread_network_server_data_entry_t *thread_get_dhcp_server_from_list(thread_network_server_data_list_t *list) 00785 { 00786 //Check current Stable List 00787 ns_list_foreach(thread_network_server_data_entry_t, cur, list) { 00788 if (cur->P_dhcp) { 00789 return cur; 00790 } 00791 } 00792 return NULL; 00793 } 00794 00795 thread_network_data_context_entry_t *thread_get_main_context_list(thread_data_context_list_t *list, thread_network_local_data_context_entry_t *context) 00796 { 00797 thread_network_data_context_entry_t *main_list; 00798 00799 //Check current Stable List 00800 ns_list_foreach(thread_network_data_context_entry_t, cur, list) { 00801 if (cur->cid == context->cid) { 00802 return cur; 00803 } 00804 } 00805 00806 main_list = thread_context_service_list_allocate(context->contextPrefixLength, context->cid, context->compression); 00807 if (main_list) { 00808 tr_debug("Add New"); 00809 ns_list_add_to_end(list, main_list); 00810 } 00811 00812 return main_list; 00813 } 00814 00815 void thread_server_list_free(thread_network_server_data_list_t *listPtr) 00816 { 00817 ns_list_foreach_safe(thread_network_server_data_entry_t, cur, listPtr) { 00818 ns_list_remove(listPtr, cur); 00819 ns_dyn_mem_free(cur); 00820 } 00821 } 00822 00823 void thread_service_server_list_free(thread_network_data_service_server_list_t *listPtr) 00824 { 00825 ns_list_foreach_safe(thread_network_data_service_server_entry_t, cur, listPtr) { 00826 if (cur->server_data) { 00827 ns_dyn_mem_free(cur->server_data); 00828 } 00829 ns_list_remove(listPtr, cur); 00830 ns_dyn_mem_free(cur); 00831 } 00832 } 00833 00834 static int thread_server_context_delete_mark(thread_data_context_list_t *listPtr) 00835 { 00836 int retVal = -1; 00837 ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { 00838 cur->canDelete = true; 00839 } 00840 return retVal; 00841 } 00842 00843 static int thread_server_data_delete_mark_by_router_id(thread_network_server_data_list_t *listPtr, uint16_t routerID, bool subSet) 00844 { 00845 int retVal = -1; 00846 ns_list_foreach_safe(thread_network_server_data_entry_t, cur, listPtr) { 00847 if (!subSet) { 00848 cur->canDelete = true; 00849 } 00850 if (cur->routerID == routerID) { 00851 cur->canDelete = true; 00852 } 00853 } 00854 return retVal; 00855 } 00856 00857 static int thread_service_data_delete_mark_by_router_id(thread_network_data_service_server_list_t *listPtr, uint16_t routerID, bool subSet) 00858 { 00859 int retVal = -1; 00860 ns_list_foreach_safe(thread_network_data_service_server_entry_t, cur, listPtr) { 00861 if (!subSet) { 00862 cur->can_delete = true; 00863 } 00864 if (cur->router_id == routerID) { 00865 cur->can_delete = true; 00866 } 00867 } 00868 return retVal; 00869 } 00870 00871 static int thread_server_context_clean(thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list) 00872 { 00873 int retVal = -1; 00874 (void) prefixEntry; 00875 ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { 00876 if (cur->canDelete) { 00877 cachePtr->temporaryUpdatePushed = true; 00878 if (cur->stableData) { 00879 cachePtr->stableUpdatePushed = true; 00880 } 00881 // Set context lifetime to 0 to delete 00882 lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); 00883 ns_list_remove(listPtr, cur); 00884 ns_dyn_mem_free(cur); 00885 retVal = 0; 00886 } 00887 } 00888 return retVal; 00889 } 00890 00891 00892 static bool thread_server_data_clean_by_router_id(thread_network_data_cache_entry_t *cachePtr, thread_network_server_data_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, bool routeInfo, protocol_interface_info_entry_t *curInterface) 00893 { 00894 uint8_t addr[16]; 00895 uint8_t *nextHop; 00896 bool address_removed = false; 00897 00898 uint16_t mac16 = mac_helper_mac16_address_get(curInterface); 00899 ns_list_foreach_safe(thread_network_server_data_entry_t, cur, listPtr) { 00900 if (cur->canDelete) { 00901 tr_debug("Delete BR %s", trace_array(prefixEntry->servicesPrefix , 8)); 00902 cachePtr->temporaryUpdatePushed = true; 00903 if (cur->stableData) { 00904 cachePtr->stableUpdatePushed = true; 00905 } 00906 //Call Route and DHCPV6 Updates here 00907 memcpy(addr, curInterface->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8); 00908 00909 memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); 00910 common_write_16_bit(cur->routerID, &addr[14]); 00911 00912 00913 if (routeInfo) { 00914 if (cur->routerID == mac16) { 00915 nextHop = NULL; 00916 } else { 00917 nextHop = addr; 00918 } 00919 if (prefixEntry) { 00920 ipv6_route_delete(prefixEntry->servicesPrefix , prefixEntry->servicesPrefixLen , curInterface->id, nextHop, ROUTE_THREAD); 00921 } else { 00922 ipv6_route_delete(NULL, 0, curInterface->id, nextHop, ROUTE_THREAD); 00923 } 00924 } else { 00925 address_removed = true; 00926 00927 if (cur->P_dhcp) { 00928 tr_debug("Delete DHCPv6 given address"); 00929 thread_dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix ); 00930 } else { 00931 tr_debug("Delete SLAAC address"); 00932 addr_delete_matching(curInterface, prefixEntry->servicesPrefix , 64, ADDR_SOURCE_SLAAC); 00933 } 00934 } 00935 00936 ns_list_remove(listPtr, cur); 00937 ns_dyn_mem_free(cur); 00938 } 00939 } 00940 return address_removed; 00941 } 00942 00943 static void thread_service_data_clean_by_router_id(thread_network_data_cache_entry_t *cachePtr, thread_network_data_service_server_list_t *listPtr) 00944 { 00945 ns_list_foreach_safe(thread_network_data_service_server_entry_t, cur, listPtr) { 00946 if (cur->can_delete) { 00947 tr_debug("Deleting server %04x", cur->router_id); 00948 cachePtr->temporaryUpdatePushed = true; 00949 if (cur->stable) { 00950 cachePtr->stableUpdatePushed = true; 00951 } 00952 if (cur->server_data) { 00953 ns_dyn_mem_free(cur->server_data); 00954 } 00955 ns_list_remove(listPtr, cur); 00956 ns_dyn_mem_free(cur); 00957 } 00958 } 00959 } 00960 00961 void thread_context_service_list_free(thread_data_context_list_t *listPtr) 00962 { 00963 ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { 00964 ns_list_remove(listPtr, cur); 00965 ns_dyn_mem_free(cur); 00966 } 00967 } 00968 00969 00970 /** 00971 * Initialise Thread Network Data cache 00972 * 00973 * \param cachePtr Pointer to Network Data Structure which will be initialized 00974 * 00975 */ 00976 void thread_network_data_base_init(thread_network_data_cache_entry_t *cachePtr) 00977 { 00978 ns_list_init(&cachePtr->localPrefixList ); 00979 ns_list_init(&cachePtr->service_list); 00980 cachePtr->contex_id_reuse_timeout = THREAD_CONTEXT_ID_REUSE_TIMEOUT; 00981 cachePtr->networkDataTlvSize = 0; 00982 cachePtr->stableUpdatePushed = false; 00983 cachePtr->temporaryUpdatePushed = false; 00984 cachePtr->network_data_update_delay = 0; 00985 cachePtr->network_data_len = 0; 00986 } 00987 00988 void thread_network_local_server_data_base_init(thread_network_local_data_cache_entry_t *cachePtr) 00989 { 00990 ns_list_init(&cachePtr->prefix_list); 00991 ns_list_init(&cachePtr->service_list); 00992 cachePtr->registered_rloc16 = 0xffff; 00993 cachePtr->release_old_address = false; 00994 cachePtr->publish_active = false; 00995 cachePtr->publish_pending = false; 00996 } 00997 00998 void thread_network_data_router_id_mark_delete(thread_network_data_cache_entry_t *cachePtr, uint16_t routerID, bool subSet) 00999 { 01000 ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList ) { 01001 thread_server_data_delete_mark_by_router_id(&cur->borderRouterList, routerID, subSet); 01002 thread_server_data_delete_mark_by_router_id(&cur->routeList, routerID, subSet); 01003 if (!subSet) { 01004 thread_server_context_delete_mark(&cur->contextList); 01005 } 01006 } 01007 01008 ns_list_foreach_safe(thread_network_data_service_cache_entry_t, cur, &cachePtr->service_list) { 01009 thread_service_data_delete_mark_by_router_id(&cur->server_list, routerID, subSet); 01010 } 01011 } 01012 bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cachePtr, bool is_leader, protocol_interface_info_entry_t *curInterface) 01013 { 01014 bool address_removed = false; 01015 ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList ) { 01016 //GET Context 01017 if (thread_server_data_clean_by_router_id(cachePtr, &cur->borderRouterList, cur, false, curInterface) ) { 01018 address_removed = true; 01019 } 01020 thread_server_data_clean_by_router_id(cachePtr, &cur->routeList, cur, true, curInterface); 01021 if (!is_leader) { 01022 thread_server_context_clean(cachePtr, &cur->contextList, cur, &curInterface->lowpan_contexts); 01023 } 01024 01025 if (ns_list_is_empty(&cur->borderRouterList)) { 01026 //Delete On-Mesh Prefix 01027 ipv6_route_delete(cur->servicesPrefix, cur->servicesPrefixLen, curInterface->id, NULL, ROUTE_THREAD); 01028 } 01029 01030 if (!ns_list_is_empty(&cur->borderRouterList)) { 01031 01032 } else if (!ns_list_is_empty(&cur->routeList)) { 01033 01034 } else if (!ns_list_is_empty(&cur->contextList)) { 01035 if (is_leader) { 01036 ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) { 01037 cachePtr->temporaryUpdatePushed = true; 01038 if (curContext->stableData) { 01039 cachePtr->stableUpdatePushed = true; 01040 } 01041 if (curContext->compression) { 01042 curContext->compression = false; 01043 tr_debug("disable Cur Context and start timer"); 01044 curContext->context_reuse_delay = cachePtr->contex_id_reuse_timeout; 01045 } 01046 } 01047 } 01048 } else { 01049 //ALL Empty 01050 ns_list_remove(&cachePtr->localPrefixList , cur); 01051 ns_dyn_mem_free(cur); 01052 } 01053 } 01054 01055 ns_list_foreach_safe(thread_network_data_service_cache_entry_t, cur, &cachePtr->service_list) { 01056 thread_service_data_clean_by_router_id(cachePtr, &cur->server_list); 01057 if (ns_list_is_empty(&cur->server_list)) { 01058 if (cur->S_service_data) { 01059 ns_dyn_mem_free(cur->S_service_data); 01060 } 01061 ns_list_remove(&cachePtr->service_list, cur); 01062 ns_dyn_mem_free(cur); 01063 } 01064 } 01065 01066 if (cachePtr->temporaryUpdatePushed || cachePtr->stableUpdatePushed) { 01067 //Validate that Length will be always updated 01068 cachePtr->networkDataTlvSize = thread_network_data_prefix_set_size(cachePtr, true) 01069 + thread_network_data_service_set_size(cachePtr, true); 01070 } 01071 return address_removed; 01072 } 01073 01074 void thread_network_data_context_re_use_timer_update(thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list) 01075 { 01076 ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList ) { 01077 ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) { 01078 if (!curContext->compression) { 01079 if (curContext->context_reuse_delay > ticks) { 01080 curContext->context_reuse_delay -= ticks; 01081 } else { 01082 ns_list_remove(&cur->contextList, curContext); 01083 if (curContext->stableData) { 01084 cachePtr->stableUpdatePushed = true; 01085 } else { 01086 cachePtr->temporaryUpdatePushed = true; 01087 } 01088 // Set context lifetime to 0 to delete 01089 lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); 01090 ns_dyn_mem_free(curContext); 01091 } 01092 } 01093 } 01094 if (ns_list_is_empty(&cur->borderRouterList) && 01095 ns_list_is_empty(&cur->routeList) && 01096 ns_list_is_empty(&cur->contextList)) { 01097 ns_list_remove(&cachePtr->localPrefixList , cur); 01098 ns_dyn_mem_free(cur); 01099 } 01100 } 01101 } 01102 01103 01104 void thread_network_data_free_and_clean(thread_network_data_cache_entry_t *cachePtr) 01105 { 01106 if (!ns_list_is_empty(&cachePtr->localPrefixList )) { 01107 ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList ) { 01108 thread_context_service_list_free(&cur->contextList); 01109 thread_server_list_free(&cur->borderRouterList); 01110 thread_server_list_free(&cur->routeList); 01111 ns_list_remove(&cachePtr->localPrefixList , cur); 01112 ns_dyn_mem_free(cur); 01113 } 01114 ns_list_init(&cachePtr->localPrefixList ); 01115 } 01116 01117 if (!ns_list_is_empty(&cachePtr->service_list)) { 01118 ns_list_foreach_safe(thread_network_data_service_cache_entry_t, cur, &cachePtr->service_list) { 01119 thread_service_server_list_free(&cur->server_list); 01120 if (cur->S_service_data) { 01121 ns_dyn_mem_free(cur->S_service_data); 01122 } 01123 ns_list_remove(&cachePtr->service_list, cur); 01124 ns_dyn_mem_free(cur); 01125 } 01126 ns_list_init(&cachePtr->service_list); 01127 } 01128 01129 cachePtr->networkDataTlvSize = 0; 01130 cachePtr->stableUpdatePushed = false; 01131 cachePtr->temporaryUpdatePushed = false; 01132 cachePtr->network_data_update_delay = 0; 01133 cachePtr->network_data_len = 0; 01134 } 01135 01136 void thread_network_local_data_free_and_clean(thread_network_local_data_cache_entry_t *cachePtr, int8_t interface_id) 01137 { 01138 ns_list_foreach_safe(thread_network_local_data_entry_t, cur, &cachePtr->prefix_list) { 01139 if (cur->dhcpv6ServerActive) { 01140 DHCPv6_server_service_delete(interface_id, cur->servicesPrefix, true); 01141 } 01142 01143 ns_list_remove(&cachePtr->prefix_list, cur); 01144 ns_dyn_mem_free(cur); 01145 } 01146 01147 ns_list_foreach_safe(thread_network_data_service_entry_t, cur, &cachePtr->service_list) { 01148 ns_list_remove(&cachePtr->service_list, cur); 01149 if (cur->S_service_data) { 01150 ns_dyn_mem_free(cur->S_service_data); 01151 } 01152 if (cur->S_server_data) { 01153 ns_dyn_mem_free(cur->S_server_data); 01154 } 01155 ns_dyn_mem_free(cur); 01156 } 01157 01158 cachePtr->publish_pending = false; 01159 cachePtr->publish_active = false; 01160 cachePtr->release_old_address = false; 01161 } 01162 01163 static bool thread_network_data_has_subtlv(uint8_t *network_data_ptr, uint16_t network_data_length, uint8_t *prefix, uint8_t prefix_length, uint8_t lookup_type) 01164 { 01165 uint8_t *dptr; 01166 uint8_t length; 01167 uint8_t type; 01168 dptr = network_data_ptr; 01169 while (network_data_length) { 01170 if (network_data_length >= 2) { 01171 type = *dptr++; 01172 type &= THREAD_NWK_DATA_TYPE_MASK; 01173 length = *dptr++; 01174 01175 if (length == 0) { 01176 return false; 01177 } 01178 network_data_length -= 2; 01179 if (network_data_length >= length) { 01180 // Set length ready for next check 01181 network_data_length -= length; 01182 01183 if (type == THREAD_NWK_DATA_TYPE_PREFIX) { 01184 thread_prefix_tlv_t prefix_tlv; 01185 prefix_tlv.domainId = *dptr++; 01186 prefix_tlv.PrefixLen = *dptr++; 01187 prefix_tlv.Prefix = dptr; 01188 length -= 2; 01189 01190 uint8_t prefix_bytes_len = prefixBits_to_bytes(prefix_tlv.PrefixLen); 01191 uint8_t prefix_bytes_length = prefixBits_to_bytes(prefix_length); 01192 01193 if (prefix_bytes_len > length) { 01194 return false; 01195 } 01196 01197 if (prefix_bytes_len != prefix_bytes_length || 01198 memcmp(prefix, prefix_tlv.Prefix, prefix_bytes_len) != 0) { 01199 dptr += length; 01200 continue; 01201 } 01202 01203 length -= prefix_bytes_len; 01204 dptr += prefix_bytes_len; 01205 01206 while (length > 2) { 01207 type = *dptr++; 01208 type &= THREAD_NWK_DATA_TYPE_MASK; 01209 uint8_t subLength = *dptr++; 01210 length -= 2; 01211 01212 if (subLength <= length) { 01213 length -= subLength; 01214 dptr += subLength; 01215 01216 if (lookup_type == type) { 01217 return true; 01218 } 01219 } else { 01220 tr_error("Length fail"); 01221 return false; 01222 } 01223 } 01224 } else { 01225 dptr += length; 01226 } 01227 } else { 01228 tr_error("Length fail"); 01229 return false; 01230 } 01231 } else { 01232 return false; 01233 } 01234 } 01235 01236 return false; 01237 } 01238 01239 static uint16_t thread_network_data_prefix_shrink_size(thread_network_data_cache_entry_t *networkDataStorage, uint8_t *network_data_ptr, uint16_t network_data_length, uint16_t router_id) 01240 { 01241 uint16_t network_data_len = 0; 01242 01243 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataStorage->localPrefixList ) { 01244 ns_list_foreach(thread_network_server_data_entry_t, br_cur, &cur->borderRouterList) { 01245 if (br_cur->routerID == router_id) { 01246 tr_debug("Checking prefix: %s", trace_ipv6_prefix(cur->servicesPrefix, cur->servicesPrefixLen)); 01247 if (!thread_network_data_has_subtlv(network_data_ptr, network_data_length, cur->servicesPrefix, cur->servicesPrefixLen, THREAD_NWK_DATA_TYPE_BORDER_ROUTER)) { 01248 if (ns_list_count(&cur->borderRouterList) == 1) { 01249 network_data_len += 2 + THREAD_BORDER_ROUTER_TLV_LENGTH; 01250 } else { 01251 network_data_len += THREAD_BORDER_ROUTER_TLV_LENGTH; 01252 } 01253 } 01254 } 01255 } 01256 01257 ns_list_foreach(thread_network_server_data_entry_t, route_cur, &cur->routeList) { 01258 if (route_cur->routerID == router_id) { 01259 if (!thread_network_data_has_subtlv(network_data_ptr, network_data_length, cur->servicesPrefix, cur->servicesPrefixLen, THREAD_NWK_DATA_TYPE_ROUTE)) { 01260 if (ns_list_count(&cur->routeList) == 1) { 01261 network_data_len += 2 + THREAD_HAS_ROUTE_TLV_LENGTH; 01262 if (ns_list_count(&cur->borderRouterList) == 0) { 01263 uint8_t prefix_bytes_len = prefixBits_to_bytes(cur->servicesPrefixLen); 01264 network_data_len += 2 + 2 + prefix_bytes_len; 01265 } 01266 } else { 01267 network_data_len += THREAD_HAS_ROUTE_TLV_LENGTH; 01268 } 01269 } 01270 } 01271 } 01272 } 01273 01274 tr_debug("Shrink size: %d", network_data_len); 01275 return network_data_len; 01276 } 01277 01278 /** 01279 * Calculates what the resulting size of prefixes for Network Data TLV would be. 01280 */ 01281 static int thread_network_data_resulting_prefix_set_size(thread_network_data_cache_entry_t *networkDataStorage, uint8_t *network_data_ptr, uint16_t network_data_length, uint16_t rid) 01282 { 01283 uint8_t *dptr; 01284 uint8_t length; 01285 uint8_t type; 01286 01287 if (!networkDataStorage || !network_data_ptr) { 01288 return -1; 01289 } 01290 01291 uint16_t network_data_len = thread_network_data_prefix_set_size(networkDataStorage, true); 01292 tr_debug("Old network data length: %d", network_data_len); 01293 01294 /* Calculate how much removed network data would reduce the total size */ 01295 network_data_len -= thread_network_data_prefix_shrink_size(networkDataStorage, network_data_ptr, network_data_length, rid); 01296 01297 dptr = network_data_ptr; 01298 while (network_data_length) { 01299 if (network_data_length >= 2) { 01300 type = *dptr++; 01301 type &= THREAD_NWK_DATA_TYPE_MASK; 01302 length = *dptr++; 01303 01304 if (length == 0) { 01305 // 0 is not valid length for TLV 01306 return -1; 01307 } 01308 01309 network_data_length -= 2; 01310 01311 if (network_data_length >= length) { 01312 // Set length ready for next check 01313 network_data_length -= length; 01314 01315 if (type == THREAD_NWK_DATA_TYPE_PREFIX) { 01316 thread_prefix_tlv_t prefix_tlv; 01317 prefix_tlv.domainId = *dptr++; 01318 prefix_tlv.PrefixLen = *dptr++; 01319 prefix_tlv.Prefix = dptr; 01320 length -= 2; 01321 01322 uint8_t prefix_bytes_len = prefixBits_to_bytes(prefix_tlv.PrefixLen); 01323 01324 if (prefix_bytes_len > length) { 01325 return -1; 01326 } 01327 01328 length -= prefix_bytes_len; 01329 dptr += prefix_bytes_len; 01330 01331 tr_debug("Prefix: %s", trace_ipv6_prefix(prefix_tlv.Prefix, prefix_tlv.PrefixLen)); 01332 thread_network_data_prefix_cache_entry_t *prefix = thread_prefix_entry_find(&networkDataStorage->localPrefixList , &prefix_tlv); 01333 01334 if (!prefix) { 01335 tr_debug("Adding new prefix!"); 01336 // This is a new prefix; add header length 01337 network_data_len += 2 + 2 + prefix_bytes_len; 01338 } 01339 01340 while (length > 2) { 01341 type = *dptr++; 01342 type &= THREAD_NWK_DATA_TYPE_MASK; 01343 uint8_t subLength = *dptr++; 01344 length -= 2; 01345 01346 tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength)); 01347 01348 if (subLength <= length) { 01349 length -= subLength; 01350 01351 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) { 01352 if (!prefix) { 01353 // Add 6LoWPAN ID length (plus type & length) 01354 network_data_len += 2 + THREAD_6LOWPAN_ID_TLV_LENGTH; 01355 } 01356 01357 while (subLength) { 01358 thread_network_server_data_entry_t *server_entry = NULL; 01359 uint16_t router_id = common_read_16_bit(dptr); 01360 dptr += 4; 01361 01362 if (prefix) { 01363 server_entry = thread_server_entry_search(&prefix->borderRouterList, router_id); 01364 } 01365 01366 if (!prefix || !server_entry) { 01367 if (!prefix || ns_list_count(&prefix->borderRouterList) == 0) { 01368 // Add Border Router type and length 01369 network_data_len += 2; 01370 } 01371 // Add Border Router TLV length 01372 network_data_len += THREAD_BORDER_ROUTER_TLV_LENGTH; 01373 } 01374 01375 subLength -= THREAD_BORDER_ROUTER_TLV_LENGTH; 01376 } 01377 01378 tr_debug("Type is BORDER ROUTER"); 01379 } else if (type == THREAD_NWK_DATA_TYPE_ROUTE) { 01380 while (subLength) { 01381 thread_network_server_data_entry_t *server_entry = NULL; 01382 uint16_t router_id = common_read_16_bit(dptr); 01383 dptr += 3; 01384 01385 if (prefix) { 01386 server_entry = thread_server_entry_search(&prefix->routeList, router_id); 01387 } 01388 01389 if (!prefix || !server_entry) { 01390 if (!prefix || ns_list_count(&prefix->routeList) == 0) { 01391 // Add Has Route type and length 01392 network_data_len += 2; 01393 } 01394 // Add Has Route TLV length 01395 network_data_len += THREAD_HAS_ROUTE_TLV_LENGTH; 01396 } 01397 01398 subLength -= THREAD_HAS_ROUTE_TLV_LENGTH; 01399 } 01400 01401 tr_debug("Type is HAS ROUTE"); 01402 } else { 01403 dptr += subLength; 01404 } 01405 } else { 01406 tr_error("Length fail"); 01407 return -1; 01408 } 01409 } 01410 } else { 01411 dptr += length; 01412 } 01413 } else { 01414 tr_error("Length fail"); 01415 return -1; 01416 } 01417 } else { 01418 return -1; 01419 } 01420 } 01421 01422 return network_data_len; 01423 } 01424 01425 /** 01426 * Calculates what the future size of Network Data TLV would be if new data was 01427 * incorporated to the old data. NOTE: Use of this function should be replaced 01428 * by some sophisticated logic to analyze if new data or part of it should be 01429 * given priority. Now we simply limit by the total size. 01430 */ 01431 int thread_network_data_resulting_tlv_size(thread_network_data_cache_entry_t *networkDataStorage, uint8_t *network_data_ptr, uint16_t network_data_length, uint16_t router_id) 01432 { 01433 int network_data_len = thread_network_data_resulting_prefix_set_size(networkDataStorage, network_data_ptr, network_data_length, router_id); 01434 01435 // TODO: Add support for other TLVs than Prefix here 01436 01437 tr_debug("Size of the prefix set: %d", network_data_len); 01438 01439 if (network_data_len >= 0) { 01440 // Add maximum Commission TLV size 01441 network_data_len += THREAD_MAX_COMM_DATA_TLV_LEN; 01442 } 01443 01444 return network_data_len; 01445 } 01446 01447 /** 01448 * Add new route information to route List 01449 * 01450 * \param networkDataList Pointer main network data structure 01451 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01452 * \param service Route TLV 01453 * 01454 * return 0, ADD OK 01455 * return <0 Add Not OK 01456 */ 01457 int thread_nd_local_list_add_route(thread_network_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *route) 01458 { 01459 thread_network_server_data_entry_t *entry; 01460 tr_debug("Add Route: %s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen)); 01461 01462 route->P_configure = false; 01463 route->P_default_route = false; 01464 route->P_dhcp = false; 01465 route->P_preferred = false; 01466 route->P_slaac = false; 01467 01468 if (!networkDataList) { 01469 return -1; 01470 } 01471 01472 thread_network_data_prefix_cache_entry_t *prefix_entry = thread_prefix_entry_get(&networkDataList->localPrefixList , prefixTlv); 01473 if (!prefix_entry) { 01474 return -1; 01475 } 01476 01477 entry = thread_server_entry_get(&prefix_entry->routeList, route); 01478 if (!entry) { 01479 return -1; 01480 } 01481 01482 entry->canDelete = false; 01483 if ((thread_nd_local_data_length_updated(networkDataList) == 0)) { 01484 if (route->stableData) { 01485 networkDataList->stableUpdatePushed = true; 01486 } else { 01487 networkDataList->temporaryUpdatePushed = true; 01488 } 01489 } else if (entry->Prf != route->Prf) { 01490 entry->Prf = route->Prf; 01491 if (route->stableData) { 01492 networkDataList->stableUpdatePushed = true; 01493 } else { 01494 networkDataList->temporaryUpdatePushed = true; 01495 } 01496 } 01497 return 0; 01498 } 01499 01500 int thread_nd_local_list_add_service(thread_network_data_cache_entry_t *networkDataList, thread_network_data_service_entry_t *service, thread_network_data_service_server_entry_t *server) 01501 { 01502 bool changed = false; 01503 tr_debug("Add Service: %s", trace_array(service->S_service_data, service->S_service_data_length)); 01504 01505 if (!networkDataList) { 01506 return -1; 01507 } 01508 01509 thread_network_data_service_cache_entry_t *service_entry = thread_service_entry_get(&networkDataList->service_list, service); 01510 if (!service_entry) { 01511 return -1; 01512 } 01513 01514 thread_network_data_service_server_entry_t *entry = thread_service_server_entry_get(&service_entry->server_list, server); 01515 if (!entry) { 01516 return -1; 01517 } 01518 01519 if (entry->server_data_length != server->server_data_length || memcmp(entry->server_data,server->server_data,server->server_data_length) != 0) { 01520 // Server data changed 01521 if (entry->server_data_length != server->server_data_length ) { 01522 ns_dyn_mem_free(entry->server_data); 01523 entry->server_data = ns_dyn_mem_alloc(server->server_data_length); 01524 if (!entry->server_data) { 01525 return -1; 01526 } 01527 } 01528 memcpy(entry->server_data,server->server_data,server->server_data_length); 01529 entry->server_data_length = server->server_data_length; 01530 changed = true; 01531 } 01532 entry->can_delete = false; 01533 01534 if (changed || (thread_nd_local_data_length_updated(networkDataList) == 0)) { 01535 if (server->stable) { 01536 networkDataList->stableUpdatePushed = true; 01537 } else { 01538 networkDataList->temporaryUpdatePushed = true; 01539 } 01540 } 01541 01542 return 0; 01543 } 01544 01545 /** 01546 * Add new BorderRouter Server information to route List 01547 * 01548 * \param networkDataList Pointer main network data structure 01549 * \param prefixTlv Prefix TLv 01550 * \param service Border Router TLV 01551 * 01552 * return 0, ADD OK 01553 * return <0 Add Not OK 01554 */ 01555 int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) 01556 { 01557 bool trigDataPropagate = false; 01558 thread_network_data_prefix_cache_entry_t *prefix_entry; 01559 thread_network_server_data_entry_t *server_entry; 01560 if (service->P_dhcp) { 01561 tr_debug("Add DHCPv6 prefix:%s server: %04x", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen),service->routerID); 01562 } else { 01563 tr_debug("Add SLAAC prefix:%s server: %04x", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen),service->routerID); 01564 } 01565 01566 if (!networkDataList) { 01567 return -1; 01568 } 01569 01570 if (!prefixTlv->PrefixLen) { 01571 return -1; 01572 } 01573 01574 prefix_entry = thread_prefix_entry_get(&networkDataList->localPrefixList , prefixTlv); 01575 if (!prefix_entry) { 01576 return -1; 01577 } 01578 01579 server_entry = thread_server_entry_get(&prefix_entry->borderRouterList, service); 01580 01581 if (!server_entry) { 01582 return -1; 01583 } 01584 tr_debug("update current BR"); 01585 01586 server_entry->canDelete = false; 01587 if (thread_nd_local_data_length_updated(networkDataList) == 0) { 01588 trigDataPropagate = true; 01589 } else { 01590 if (server_entry->P_configure != service->P_configure) { 01591 server_entry->P_configure = service->P_configure; 01592 trigDataPropagate = true; 01593 } 01594 01595 if (server_entry->P_default_route != service->P_default_route) { 01596 server_entry->P_default_route = service->P_default_route; 01597 trigDataPropagate = true; 01598 } 01599 01600 if (server_entry->Prf != service->Prf) { 01601 server_entry->Prf = service->Prf; 01602 trigDataPropagate = true; 01603 } 01604 01605 if (server_entry->P_preferred != service->P_preferred || server_entry->P_slaac != service->P_slaac) { 01606 server_entry->P_preferred = service->P_preferred; 01607 server_entry->P_slaac = service->P_slaac; 01608 trigDataPropagate = true; 01609 } 01610 01611 if (server_entry->P_dhcp != service->P_dhcp) { 01612 server_entry->P_dhcp = service->P_dhcp; 01613 trigDataPropagate = true; 01614 } 01615 01616 if (server_entry->P_on_mesh != service->P_on_mesh) { 01617 server_entry->P_on_mesh = service->P_on_mesh; 01618 trigDataPropagate = true; 01619 } 01620 01621 if (server_entry->P_nd_dns != service->P_nd_dns) { 01622 server_entry->P_nd_dns = service->P_nd_dns; 01623 trigDataPropagate = true; 01624 } 01625 } 01626 01627 if (trigDataPropagate) { 01628 if (service->stableData) { 01629 networkDataList->stableUpdatePushed = true; 01630 } else { 01631 networkDataList->temporaryUpdatePushed = true; 01632 } 01633 } 01634 01635 return 0; 01636 } 01637 01638 01639 /** 01640 * Del DHCPv6 Server information to route List 01641 * 01642 * \param networkDataList Pointer main network data structure 01643 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01644 * \param service On Mesh prefix TLV 01645 * 01646 * return 0, Del OK 01647 * return <0 Del Not OK 01648 */ 01649 int thread_nd_local_list_del_on_mesh_server(thread_network_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) 01650 { 01651 thread_network_data_prefix_cache_entry_t *main_list; 01652 thread_network_server_data_entry_t *entry; 01653 01654 if (!networkDataList) { 01655 return -1; 01656 } 01657 01658 if (prefixTlv->PrefixLen) { 01659 return -1; 01660 } 01661 01662 if (service->P_dhcp) { 01663 tr_debug("Del DHCPv6 server: %s", 01664 trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen))); 01665 } else { 01666 tr_debug("Del SLAAC server: %s", 01667 trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen))); 01668 } 01669 01670 main_list = thread_prefix_entry_get(&networkDataList->localPrefixList , prefixTlv); 01671 if (!main_list) { 01672 return -1; 01673 } 01674 01675 entry = thread_server_entry_search(&main_list->borderRouterList, service->routerID); 01676 01677 if (!entry) { 01678 return -1; 01679 } 01680 01681 entry->canDelete = true; 01682 if (entry->stableData) { 01683 networkDataList->stableUpdatePushed = true; 01684 } else { 01685 networkDataList->temporaryUpdatePushed = true; 01686 } 01687 01688 return 0; 01689 } 01690 01691 /** 01692 * Add new Local DHCPv6 Server information to route List 01693 * 01694 * \param networkDataList Pointer main network data structure 01695 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01696 * \param service On Mesh prefix TLV 01697 * 01698 * return 0, ADD OK 01699 * return <0 Add Not OK 01700 */ 01701 int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) 01702 { 01703 int retVal = -1; 01704 tr_debug("Add prefix: %s prf:%d %s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, 01705 service->P_default_route?"Default Route ":"",service->P_dhcp?"DHCPv6 Server ":"", service->P_configure?"DHCPv6 Configuration ":"", 01706 service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":""); 01707 01708 if (networkDataList) { 01709 thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv); 01710 if (prefix_entry) { 01711 prefix_entry->preference = service->Prf; 01712 prefix_entry->configure = service->P_configure; 01713 prefix_entry->defaultRoute = service->P_default_route; 01714 prefix_entry->onMesh = service->P_on_mesh; 01715 prefix_entry->ndDns = service->P_nd_dns; 01716 01717 if (service->P_dhcp) { 01718 prefix_entry->dhcpv6ServerActive = true; 01719 prefix_entry->dhcpv6ServerDataStable = service->stableData; 01720 } 01721 01722 if (service->P_slaac) { 01723 prefix_entry->slaacServerActive = true; 01724 prefix_entry->slaacServerDataStable = service->stableData; 01725 prefix_entry->slaacPreferred = service->P_preferred; 01726 } 01727 01728 if (prefixTlv->PrefixLen == 0) { 01729 // Adding as default route ::/0 01730 prefix_entry->routeActive = true; 01731 prefix_entry->routeDataStable = service->stableData; 01732 } 01733 retVal = 0; 01734 } 01735 } 01736 return retVal; 01737 } 01738 01739 /** 01740 * Del Local DHCPv6 Server information to route List 01741 * 01742 * \param networkDataList Pointer main network data structure 01743 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01744 * 01745 * return 0, Del OK 01746 * return <0 Del Not OK 01747 */ 01748 int thread_local_server_list_del_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv) 01749 { 01750 thread_network_local_data_entry_t *prefix_entry; 01751 01752 if (!networkDataList) { 01753 return -1; 01754 } 01755 01756 tr_debug("Delete prefix %s", trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen))); 01757 01758 prefix_entry = thread_local_prefix_entry_find(&networkDataList->prefix_list, prefixTlv); 01759 if (!prefix_entry) { 01760 return -1; 01761 } 01762 01763 tr_debug("Prefix deleted"); 01764 //Delete Entry 01765 ns_list_remove(&networkDataList->prefix_list, prefix_entry); 01766 ns_dyn_mem_free(prefix_entry); 01767 return 0; 01768 } 01769 01770 /** 01771 * Modify or add new service information to the local service list. 01772 * 01773 * \param networkDataList Pointer main network data structure. 01774 * \param service Service information to store to the list. 01775 * 01776 * return 0, Operation OK 01777 * return <0 Operation not OK 01778 */ 01779 int thread_local_service_list_add(thread_network_local_data_cache_entry_t *networkDataList, thread_network_data_service_entry_t *service) 01780 { 01781 if (!networkDataList) { 01782 return -1; 01783 } 01784 01785 tr_debug("Add service %"PRIu32": %s", service->S_enterprise_number, trace_array(service->S_service_data, service->S_service_data_length)); 01786 01787 thread_network_data_service_entry_t *service_entry = thread_local_service_entry_save(&networkDataList->service_list, service); 01788 01789 if (!service_entry) { 01790 return -1; 01791 } 01792 01793 tr_debug("Service added"); 01794 01795 return 0; 01796 } 01797 01798 /** 01799 * Delete service information from the local service list. 01800 * 01801 * \param networkDataList Pointer main network data structure 01802 * \param service Service information to use in deletion. 01803 * 01804 * return 0, Delete OK 01805 * return <0 Delete not OK 01806 */ 01807 int thread_local_service_list_del(thread_network_local_data_cache_entry_t *networkDataList, thread_network_data_service_entry_t *service) 01808 { 01809 thread_network_data_service_entry_t *service_entry; 01810 01811 if (!networkDataList || !service) { 01812 return -1; 01813 } 01814 01815 tr_debug("Delete service %"PRIu32": %s", service->S_enterprise_number, trace_array(service->S_service_data, service->S_service_data_length)); 01816 01817 service_entry = thread_local_service_entry_find(&networkDataList->service_list, service); 01818 01819 if (!service_entry) { 01820 return -1; 01821 } 01822 01823 tr_debug("Service deleted"); 01824 01825 ns_list_remove(&networkDataList->service_list, service_entry); 01826 01827 ns_dyn_mem_free(service_entry->S_service_data); 01828 01829 if (service_entry->S_server_data) { 01830 ns_dyn_mem_free(service_entry->S_server_data); 01831 } 01832 01833 ns_dyn_mem_free(service_entry); 01834 return 0; 01835 } 01836 01837 /** 01838 * Add new local route information to route List 01839 * 01840 * \param networkDataList Pointer main network data structure 01841 * \param routePrefixPtr pointer to route prefix 01842 * \param prefixLength indicate prefix pointer valid information in bits 01843 * \param stableService Boolean true generate stable service, false temporary 01844 * 01845 * return 0, ADD OK 01846 * return <0 Add Not OK 01847 */ 01848 int thread_local_server_add_route(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *route) 01849 { 01850 tr_debug("Add Route: %s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen)); 01851 01852 if (!networkDataList) { 01853 return -1; 01854 } 01855 01856 thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv); 01857 if (!prefix_entry) { 01858 return -1; 01859 } 01860 01861 prefix_entry->routeActive = true; 01862 prefix_entry->routeDataStable = route->stableData; 01863 prefix_entry->preference = route->Prf; 01864 01865 return 0; 01866 } 01867 01868 01869 /** 01870 * Del local route information to route List 01871 * 01872 * \param networkDataList Pointer main network data structure 01873 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01874 * 01875 * return 0, Del OK 01876 * return <0 Del Not OK 01877 */ 01878 int thread_local_server_del_route(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv) 01879 { 01880 thread_network_local_data_entry_t *prefix_entry; 01881 tr_debug("Del Route: %s", 01882 trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen))); 01883 01884 if (!networkDataList) { 01885 return -1; 01886 } 01887 01888 prefix_entry = thread_local_prefix_entry_find(&networkDataList->prefix_list, prefixTlv); 01889 if (!prefix_entry) { 01890 return -1; 01891 } 01892 01893 prefix_entry->routeActive = false; 01894 if (prefix_entry->dhcpv6ServerActive) { 01895 return 0; 01896 } else if (prefix_entry->slaacServerActive) { 01897 return 0; 01898 } 01899 01900 tr_debug("Free Entry"); 01901 //Delete Entry 01902 ns_list_remove(&networkDataList->prefix_list, prefix_entry); 01903 ns_dyn_mem_free(prefix_entry); 01904 01905 return 0; 01906 } 01907 01908 static bool thread_nd_public_contex_id_allocated(thread_network_data_cache_entry_t *networkDataList, uint8_t tempId) 01909 { 01910 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 01911 if (thread_get_context_by_id(&cur->contextList, tempId)) { 01912 return true; 01913 } 01914 } 01915 return false; 01916 } 01917 01918 /** 01919 * Add new 6LoWPAN contexts information to Network Data list 01920 * 01921 * \param networkDataList Network Interface 01922 * \param prefixPtr pointer 6LoWPAN Contexts 01923 * \param prefixLength indicate prefix pointer valid information in bits 01924 * 01925 * return 0, ADD OK 01926 * return <0 Add Not OK 01927 */ 01928 uint8_t thread_nd_context_id_allocate(thread_network_data_cache_entry_t *networkDataList, thread_network_local_data_cache_entry_t *localDataList, uint8_t *prefixPtr, uint8_t prefixLength) 01929 { 01930 uint8_t cid = 16; 01931 uint8_t tempId; 01932 01933 tr_debug("Disvover Context id for: %s", 01934 trace_ipv6_prefix(prefixPtr, prefixLength)); 01935 01936 if (!networkDataList || !localDataList) { 01937 return cid; 01938 } else if (!prefixLength) { 01939 return cid; 01940 } 01941 01942 //Check first is context already allocated 01943 01944 //Check Fisrt Public list 01945 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 01946 if (cur->servicesPrefixLen >= prefixLength) { 01947 if (bitsequal(cur->servicesPrefix, prefixPtr, prefixLength)) { 01948 01949 //Check Prefix context List 01950 tempId = thread_get_context_id_by_length(&cur->contextList, prefixLength); 01951 if (tempId != 16) { 01952 return tempId; 01953 } 01954 } 01955 } 01956 } 01957 01958 //Allocate Free context id 01959 if (thread_extension_version_check(thread_version)) { 01960 tempId = 2; 01961 } else { 01962 tempId = 1; 01963 } 01964 for (; tempId < 16; tempId++) { 01965 if (thread_nd_public_contex_id_allocated(networkDataList, tempId)) { 01966 //Allocated 01967 } else { 01968 cid = tempId; 01969 break; 01970 } 01971 } 01972 01973 return cid; 01974 } 01975 01976 01977 /** 01978 * Add new 6LoWPAN contexts information to Network Data list 01979 * 01980 * \param networkDataList Network Data structure pointer 01981 * \param prefixTlv Prefix TLV (domainID, Prefix, PrefixLen) 01982 * \param context Context TLV 01983 * 01984 * return 0, ADD OK 01985 * return <0 Add Not OK 01986 */ 01987 int thread_nd_local_list_add_contexts(thread_network_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_network_local_data_context_entry_t *context) 01988 { 01989 thread_network_data_prefix_cache_entry_t *main_list; 01990 thread_network_data_context_entry_t *cur; 01991 tr_debug("Add Public Context: %s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen)); 01992 01993 if (!networkDataList) { 01994 return -1; 01995 } 01996 01997 if (!prefixTlv->PrefixLen) { 01998 return -1; 01999 } 02000 02001 main_list = thread_prefix_entry_get(&networkDataList->localPrefixList , prefixTlv); 02002 if (!main_list) { 02003 return -1; 02004 } 02005 02006 cur = thread_get_main_context_list(&main_list->contextList, context); 02007 if (!cur) { 02008 return -1; 02009 } 02010 cur->canDelete = false; 02011 if (context->stableData == true) { 02012 cur->stableData = true; 02013 } 02014 cur->compression = context->compression; 02015 cur->contextPrefixLength = context->contextPrefixLength; 02016 02017 return 0; 02018 } 02019 02020 uint8_t thread_server_prefix_length(thread_network_local_data_entry_t *cur) 02021 { 02022 uint8_t tempLength = 0; 02023 02024 02025 if (cur->routeActive) { 02026 if (!((cur->slaacServerActive || cur->dhcpv6ServerActive) && cur->defaultRoute)) { 02027 // HasRoute is added if BorderRouter TLV does not have default route bit 02028 tempLength += 5; 02029 } 02030 } 02031 02032 if (cur->dhcpv6ServerActive) { 02033 tempLength += 6; 02034 } 02035 02036 if (cur->slaacServerActive) { 02037 tempLength += 6; 02038 } 02039 02040 if (tempLength) { 02041 tempLength += prefixBits_to_bytes(cur->servicesPrefixLen); 02042 tempLength += 2; //Length &domainId 02043 } 02044 02045 return tempLength; 02046 } 02047 02048 static uint8_t thread_service_length(thread_network_data_service_entry_t *cur) 02049 { 02050 uint8_t length = 0; 02051 02052 length += 1; // T + S_id 02053 02054 if (!cur->T) { 02055 length += 4; // S_enterprise_number 02056 } 02057 02058 // Service data length + service data 02059 length += 1 + cur->S_service_data_length; 02060 02061 if (cur->S_server_data) { 02062 length += 2; // Sub-TLV's type & length 02063 length += 2; // S_server_16 02064 length += cur->S_server_data_length; 02065 } 02066 02067 return length; 02068 } 02069 02070 uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_entry_t *serverDataList) 02071 { 02072 uint16_t localDataLength = 0; 02073 uint16_t tempLength; 02074 02075 ns_list_foreach(thread_network_data_service_entry_t, cur, &serverDataList->service_list) { 02076 tempLength = thread_service_length(cur); 02077 if (tempLength) { 02078 localDataLength += tempLength + 2; //Type & Length for service 02079 } 02080 } 02081 02082 ns_list_foreach(thread_network_local_data_entry_t, cur, &serverDataList->prefix_list) { 02083 tempLength = thread_server_prefix_length(cur); 02084 if (tempLength) { 02085 localDataLength += tempLength + 2; //Type & Length for prefix 02086 } 02087 } 02088 02089 return localDataLength; 02090 } 02091 02092 static bool thread_check_local_data_prefix_stable_boolean(thread_network_local_data_entry_t *dataList) 02093 { 02094 if (dataList->dhcpv6ServerActive && dataList->dhcpv6ServerDataStable) { 02095 return true; 02096 } 02097 02098 if (dataList->slaacServerActive && dataList->slaacServerDataStable) { 02099 return true; 02100 } 02101 02102 return false; 02103 } 02104 02105 static uint8_t *thread_nd_hosted_prefix_header_write(uint8_t *ptr, uint8_t length,thread_network_local_data_entry_t *cur) 02106 { 02107 uint8_t prefixBytesLen = prefixBits_to_bytes(cur->servicesPrefixLen); 02108 if (thread_check_local_data_prefix_stable_boolean(cur)) { 02109 *ptr++ = THREAD_NWK_DATA_TYPE_PREFIX | THREAD_NWK_STABLE_DATA; 02110 } else { 02111 *ptr++ = THREAD_NWK_DATA_TYPE_PREFIX; 02112 } 02113 *ptr++ = length; 02114 *ptr++ = cur->domainId; 02115 *ptr++ = cur->servicesPrefixLen; 02116 if (prefixBytesLen) { 02117 memset(ptr, 0, prefixBytesLen); 02118 bitcopy(ptr, cur->servicesPrefix, cur->servicesPrefixLen); 02119 ptr += prefixBytesLen; 02120 } 02121 return ptr; 02122 } 02123 02124 static uint8_t *thread_nd_hosted_service_header_write(uint8_t *ptr, uint8_t length, thread_network_data_service_entry_t *cur) 02125 { 02126 if (cur->S_stable) { 02127 *ptr++ = THREAD_NWK_DATA_TYPE_SERVICE_DATA | THREAD_NWK_STABLE_DATA; 02128 } else { 02129 *ptr++ = THREAD_NWK_DATA_TYPE_SERVICE_DATA; 02130 } 02131 02132 *ptr++ = length; 02133 *ptr++ = (cur->T << 7) | cur->S_id; 02134 02135 if (!cur->T) { 02136 ptr = common_write_32_bit(cur->S_enterprise_number, ptr); 02137 } 02138 02139 *ptr++ = cur->S_service_data_length; 02140 02141 memcpy(ptr, cur->S_service_data, cur->S_service_data_length); 02142 ptr += cur->S_service_data_length; 02143 02144 return ptr; 02145 } 02146 02147 static bool thread_nd_network_data_prefix_stable(thread_network_data_prefix_cache_entry_t *dataList) 02148 { 02149 ns_list_foreach(thread_network_server_data_entry_t, cur, &dataList->borderRouterList) { 02150 if (cur->stableData) { 02151 return true; 02152 } 02153 } 02154 ns_list_foreach(thread_network_server_data_entry_t, cur, &dataList->routeList) { 02155 if (cur->stableData) { 02156 return true; 02157 } 02158 } 02159 ns_list_foreach(thread_network_data_context_entry_t, cur, &dataList->contextList) { 02160 if (cur->stableData) { 02161 return true; 02162 } 02163 } 02164 return false; 02165 } 02166 02167 static uint8_t *thread_nd_prefix_header_write(uint8_t *ptr, thread_network_data_prefix_cache_entry_t *cur, uint8_t tlvLength) 02168 { 02169 uint8_t prefixBytesLen = prefixBits_to_bytes(cur->servicesPrefixLen ); 02170 if (thread_nd_network_data_prefix_stable(cur)) { 02171 *ptr++ = THREAD_NWK_DATA_TYPE_PREFIX | THREAD_NWK_STABLE_DATA; 02172 } else { 02173 *ptr++ = THREAD_NWK_DATA_TYPE_PREFIX; 02174 } 02175 *ptr++ = tlvLength; 02176 *ptr++ = cur->domainId; 02177 *ptr++ = cur->servicesPrefixLen ; 02178 if (prefixBytesLen) { 02179 memcpy(ptr, cur->servicesPrefix , prefixBytesLen); 02180 ptr += prefixBytesLen; 02181 } 02182 02183 return ptr; 02184 } 02185 02186 static bool thread_nd_network_data_service_stable(thread_network_data_service_cache_entry_t *dataList) 02187 { 02188 ns_list_foreach(thread_network_data_service_server_entry_t, cur, &dataList->server_list) { 02189 if (cur->stable) { 02190 return true; 02191 } 02192 } 02193 return false; 02194 } 02195 02196 static uint8_t *thread_nd_service_header_write(uint8_t *ptr, thread_network_data_service_cache_entry_t *cur, uint8_t tlvLength) 02197 { 02198 if (thread_nd_network_data_service_stable(cur)) { 02199 *ptr++ = THREAD_NWK_DATA_TYPE_SERVICE_DATA | THREAD_NWK_STABLE_DATA; 02200 } else { 02201 *ptr++ = THREAD_NWK_DATA_TYPE_SERVICE_DATA; 02202 } 02203 02204 *ptr++ = tlvLength; 02205 *ptr++ = (cur->T << 7) | cur->S_id; 02206 02207 if (!cur->T) { 02208 ptr = common_write_32_bit(cur->S_enterprise_number, ptr); 02209 } 02210 02211 *ptr++ = cur->S_service_data_length; 02212 02213 memcpy(ptr, cur->S_service_data, cur->S_service_data_length); 02214 ptr += cur->S_service_data_length; 02215 02216 return ptr; 02217 } 02218 02219 static uint8_t *thread_nd_hosted_service_server_write(uint8_t *ptr, uint16_t router_id, thread_network_data_service_entry_t *cur) 02220 { 02221 if (cur->S_stable) { 02222 *ptr++ = THREAD_NWK_DATA_TYPE_SERVER_DATA | THREAD_NWK_STABLE_DATA; 02223 } else { 02224 *ptr++ = THREAD_NWK_DATA_TYPE_SERVER_DATA; 02225 } 02226 02227 *ptr++ = 2 + cur->S_server_data_length; 02228 ptr = common_write_16_bit(router_id, ptr); 02229 02230 memcpy(ptr, cur->S_server_data, cur->S_server_data_length); 02231 ptr += cur->S_server_data_length; 02232 02233 return ptr; 02234 } 02235 02236 static uint8_t *thread_service_border_router_tlv_write(uint8_t *ptr, uint8_t tlvType, uint16_t routerId, uint16_t flags) 02237 { 02238 *ptr++ = tlvType; 02239 *ptr++ = THREAD_BORDER_ROUTER_TLV_LENGTH; 02240 ptr = thread_nd_network_data_border_router_tlv_write(ptr, routerId, flags); 02241 return ptr; 02242 } 02243 02244 static uint8_t *thread_service_has_route_tlv_write(uint8_t *ptr, uint8_t tlvType, uint16_t routerId, uint8_t preference) 02245 { 02246 *ptr++ = tlvType; 02247 *ptr++ = THREAD_HAS_ROUTE_TLV_LENGTH; 02248 ptr = thread_nd_network_data_has_route_tlv_write(ptr, routerId, preference); 02249 return ptr; 02250 } 02251 02252 uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_entry_t *serverDataList, uint8_t *ptr, uint16_t routerID) 02253 { 02254 uint8_t tlvType; 02255 uint8_t servicesLen; 02256 02257 ns_list_foreach(thread_network_data_service_entry_t, cur, &serverDataList->service_list) { 02258 servicesLen = thread_service_length(cur); 02259 if (servicesLen) { 02260 ptr = thread_nd_hosted_service_header_write(ptr, servicesLen, cur); 02261 if (cur->S_server_data) { 02262 ptr = thread_nd_hosted_service_server_write(ptr, routerID, cur); 02263 } 02264 } 02265 } 02266 02267 ns_list_foreach(thread_network_local_data_entry_t, cur, &serverDataList->prefix_list) { 02268 servicesLen = thread_server_prefix_length(cur); 02269 if (servicesLen) { 02270 ptr = thread_nd_hosted_prefix_header_write(ptr,servicesLen, cur); 02271 if (cur->routeActive) { 02272 if (!((cur->slaacServerActive || cur->dhcpv6ServerActive) && cur->defaultRoute)) { 02273 // HasRoute is added if BorderRouter TLV does not have default route bit 02274 uint8_t preference = 0; 02275 tlvType = THREAD_NWK_DATA_TYPE_ROUTE; 02276 if (cur->routeDataStable) { 02277 tlvType |= THREAD_NWK_STABLE_DATA; 02278 } 02279 if (cur->preference) { 02280 preference |= cur->preference << THREAD_HAS_ROUTE_PRF_BIT_MOVE; 02281 } 02282 ptr = thread_service_has_route_tlv_write(ptr, tlvType, routerID, preference); 02283 } 02284 } 02285 02286 if (cur->slaacServerActive || cur->dhcpv6ServerActive) { 02287 uint16_t flags = 0; 02288 tlvType = THREAD_NWK_DATA_TYPE_BORDER_ROUTER; 02289 if (cur->slaacServerDataStable || cur->dhcpv6ServerDataStable) { 02290 tlvType |= THREAD_NWK_STABLE_DATA; 02291 } 02292 if (cur->slaacServerActive) { 02293 flags |= 1 << THREAD_P_SLAAC_BIT_MOVE; 02294 } 02295 if (cur->dhcpv6ServerActive) { 02296 flags |= 1 << THREAD_P_DHCP_BIT_MOVE; 02297 } 02298 if (cur->slaacPreferred) { 02299 flags |= 1 << THREAD_P_PREFERRED_BIT_MOVE; 02300 } 02301 if (cur->preference) { 02302 flags |= cur->preference << THREAD_PRF_BIT_MOVE; 02303 } 02304 if (cur->configure) { 02305 flags |= 1 << THREAD_P_CONFIGURE_BIT_MOVE; 02306 } 02307 if (cur->defaultRoute) { 02308 flags |= 1 << THREAD_P_DEF_ROUTE_BIT_MOVE; 02309 } 02310 if (cur->onMesh) { 02311 flags |= 1 << THREAD_P_ON_MESH_BIT_MOVE; 02312 } 02313 if (cur->ndDns) { 02314 flags |= 1 << THREAD_P_ND_DNS_BIT_MOVE; 02315 } 02316 ptr = thread_service_border_router_tlv_write(ptr, tlvType, routerID, flags); 02317 } // slaac or dhcp 02318 } 02319 } 02320 return ptr; 02321 } 02322 02323 bool thread_nd_dhcp_anycast_address_mapping_from_network_data(thread_network_data_cache_entry_t *networkDataList, uint16_t *rlocAddress, uint8_t contexId) 02324 { 02325 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 02326 if (thread_get_context_by_id(&cur->contextList, contexId)) { 02327 //Check current Stable List 02328 thread_network_server_data_entry_t *server = thread_get_dhcp_server_from_list(&cur->borderRouterList); 02329 if (server) { 02330 *rlocAddress = server->routerID; 02331 return true; 02332 } 02333 return false; 02334 } 02335 } 02336 return false; 02337 } 02338 02339 bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_data_cache_entry_t *networkDataList, uint16_t *rlocAddress, uint8_t S_id) 02340 { 02341 ns_list_foreach(thread_network_data_service_cache_entry_t, curService, &networkDataList->service_list) { 02342 // Go through all services 02343 if (curService->S_id != S_id) { 02344 continue; 02345 } 02346 ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) { 02347 *rlocAddress = curServiceServer->router_id; 02348 return true; 02349 } 02350 } 02351 return false; 02352 } 02353 02354 bool thread_nd_on_mesh_address_valid(thread_network_server_data_entry_t *curRoute) 02355 { 02356 bool onMeshActive = false; 02357 if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred) { 02358 onMeshActive = true; 02359 } 02360 02361 return onMeshActive; 02362 } 02363 02364 thread_network_server_data_entry_t *thread_nd_hosted_by_this_routerid(uint16_t routerId, thread_network_server_data_list_t *list) 02365 { 02366 ns_list_foreach(thread_network_server_data_entry_t, curInfo, list) { 02367 if (curInfo->routerID == routerId) { 02368 return curInfo; 02369 } 02370 } 02371 return NULL; 02372 } 02373 bool thread_network_data_services_registered(thread_network_data_cache_entry_t *cachePtr, uint16_t routerID) 02374 { 02375 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList ) { 02376 if (thread_nd_hosted_by_this_routerid(routerID, &cur->borderRouterList)) { 02377 return true; 02378 } 02379 if (thread_nd_hosted_by_this_routerid(routerID, &cur->routeList)) { 02380 return true; 02381 } 02382 } 02383 return false; 02384 } 02385 02386 uint16_t thread_network_data_service_set_size(thread_network_data_cache_entry_t *networkDataList, bool fullList) 02387 { 02388 uint16_t localDataLength = 0; 02389 uint16_t tempLength; 02390 02391 ns_list_foreach(thread_network_data_service_cache_entry_t, cur, &networkDataList->service_list) { 02392 tempLength = thread_nd_service_based_on_list_entry_size(cur, fullList); 02393 if (tempLength) { 02394 localDataLength += tempLength + 2; //Type & Length for service 02395 } 02396 } 02397 02398 return localDataLength; 02399 } 02400 02401 uint16_t thread_network_data_prefix_set_size(thread_network_data_cache_entry_t *networkDataList, bool fullList) 02402 { 02403 uint16_t localDataLength = 0; 02404 uint16_t tempLength; 02405 02406 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 02407 tempLength = thread_nd_prefix_based_on_list_entry_size(cur, fullList); 02408 if (tempLength) { 02409 localDataLength += tempLength + 2; //Type & Length for prefix 02410 } 02411 } 02412 02413 return localDataLength; 02414 } 02415 02416 uint8_t *thread_network_data_prefix_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr) 02417 { 02418 uint8_t tlvLength; 02419 02420 //Add always Prefix based data first and Border Router List after That 02421 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 02422 tlvLength = thread_nd_prefix_based_on_list_entry_size(cur, true); 02423 if (tlvLength) { 02424 ptr = thread_nd_prefix_header_write(ptr, cur, tlvLength); 02425 tr_debug("Prefix: %s", trace_ipv6_prefix(cur->servicesPrefix, cur->servicesPrefixLen)); 02426 02427 //Follow canonical order first temporary data and then stable 02428 //Stable & Temporary subTLVS need to be smallest first also 02429 //SET Route always to 1. THREAD_NWK_DATA_TYPE_ROUTE 02430 //DHCPv6 Services 2. THREAD_NWK_DATA_TYPE_BORDER_ROUTER 02431 //SET Context always to 3. THREAD_NWK_DATA_TYPE_6LOWPAN_ID 02432 02433 //write Temporary List this includes the stable and unstable servers with correct address. 02434 ptr = thread_nd_server_list_write(&cur->routeList, ptr, THREAD_NWK_DATA_TYPE_ROUTE, false); 02435 ptr = thread_nd_server_list_write(&cur->borderRouterList, ptr, THREAD_NWK_DATA_TYPE_BORDER_ROUTER, false); 02436 ptr = thread_nd_context_list_write(&cur->contextList, ptr, false); 02437 02438 ptr = thread_nd_server_list_write(&cur->routeList, ptr, THREAD_NWK_DATA_TYPE_ROUTE, true); 02439 ptr = thread_nd_server_list_write(&cur->borderRouterList, ptr, THREAD_NWK_DATA_TYPE_BORDER_ROUTER, true); 02440 ptr = thread_nd_context_list_write(&cur->contextList, ptr, true); 02441 } 02442 } 02443 return ptr; 02444 } 02445 02446 uint8_t *thread_network_data_service_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr) 02447 { 02448 uint8_t tlvLength; 02449 02450 ns_list_foreach(thread_network_data_service_cache_entry_t, cur, &networkDataList->service_list) { 02451 tlvLength = thread_nd_service_based_on_list_entry_size(cur, true); 02452 if (tlvLength) { 02453 ptr = thread_nd_service_header_write(ptr, cur, tlvLength); 02454 tr_debug("Service: sid:%d e:%d data:%s",cur->S_id, cur->S_enterprise_number, trace_array(cur->S_service_data, cur->S_service_data_length)); 02455 ptr = thread_nd_service_server_list_write(&cur->server_list, ptr, true); 02456 } 02457 } 02458 02459 return ptr; 02460 } 02461 02462 bool thread_network_data_service_hosted_by_this_router_id(thread_network_data_service_cache_entry_t *dataList, uint16_t router_id) 02463 { 02464 ns_list_foreach(thread_network_data_service_server_entry_t, cur, &dataList->server_list) { 02465 if (cur->router_id == router_id) { 02466 return true; 02467 } 02468 } 02469 return false; 02470 } 02471 02472 uint16_t thread_network_data_service_child_id_from_networkdata_get(thread_network_data_cache_entry_t *networkDataList, uint16_t router_short_addr) 02473 { 02474 ns_list_foreach(thread_network_data_service_cache_entry_t, service, &networkDataList->service_list) { 02475 ns_list_foreach(thread_network_data_service_server_entry_t, server, &service->server_list) { 02476 if (thread_addr_is_child(router_short_addr, server->router_id)) { 02477 return server->router_id; 02478 } 02479 } 02480 } 02481 02482 ns_list_foreach(thread_network_data_prefix_cache_entry_t, cur, &networkDataList->localPrefixList ) { 02483 ns_list_foreach(thread_network_server_data_entry_t, curRoute, &cur->routeList) { 02484 if (thread_addr_is_child(router_short_addr, curRoute->routerID)) { 02485 return curRoute->routerID; 02486 } 02487 } 02488 02489 ns_list_foreach(thread_network_server_data_entry_t, curBR, &cur->borderRouterList) { 02490 if (thread_addr_is_child(router_short_addr, curBR->routerID)) { 02491 return curBR->routerID; 02492 } 02493 } 02494 } 02495 02496 return 0; 02497 } 02498 #endif
Generated on Tue Jul 12 2022 13:03:21 by
