Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers border_router.c Source File

border_router.c

00001 /*
00002  * Copyright (c) 2012-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include "ns_types.h"
00020 #include "string.h"
00021 #include "ns_trace.h"
00022 #include "nsdynmemLIB.h"
00023 #include "NWK_INTERFACE/Include/protocol.h"
00024 #include "NWK_INTERFACE/Include/protocol_timer.h"
00025 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00026 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00027 #ifndef NO_MLE
00028 #include "MLE/mle.h"
00029 #endif
00030 #include "mac_api.h"
00031 
00032 #include "RPL/rpl_control.h"
00033 #include "6LoWPAN/ND/nd_router_object.h"
00034 #include "Service_Libs/whiteboard/whiteboard.h"
00035 #include "Service_Libs/blacklist/blacklist.h"
00036 #include "Service_Libs/nd_proxy/nd_proxy.h"
00037 #include "shalib.h"
00038 
00039 #ifdef ECC
00040 #include "libX509_V3.h"
00041 #include "ecc.h"
00042 #endif
00043 #include "Security/TLS/tls_lib.h"
00044 #include "Security/Common/sec_lib.h"
00045 #include "net_nvm_api.h"
00046 #include "Security/PANA/pana.h"
00047 #include "Security/PANA/pana_internal_api.h"
00048 #include "Common_Protocols/ipv6.h"
00049 #include "Common_Protocols/icmpv6.h"
00050 #include "Common_Protocols/icmpv6_prefix.h"
00051 #include "Common_Protocols/icmpv6_radv.h"
00052 #include "ipv6_stack/protocol_ipv6.h"
00053 #include "common_functions.h"
00054 #include "net_thread_test.h"
00055 #include "6LoWPAN/Thread/thread_common.h"
00056 #include "6LoWPAN/Thread/thread_bootstrap.h"
00057 #include "6LoWPAN/Thread/thread_routing.h"
00058 #include "BorderRouter/border_router.h"
00059 #include "6LoWPAN/MAC/mac_helper.h"
00060 #include "6LoWPAN/MAC/beacon_handler.h"
00061 #include "6LoWPAN/NVM/nwk_nvm.h"
00062 #include "libNET/src/net_load_balance_internal.h"
00063 #include "6LoWPAN/lowpan_adaptation_interface.h"
00064 #include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
00065 
00066 #ifdef HAVE_6LOWPAN_BORDER_ROUTER
00067 
00068 #define TRACE_GROUP_BORDER_ROUTER  "br"
00069 
00070 #define TRACE_GROUP  "br"
00071 
00072 
00073 static int8_t border_router_nd_abro_periodically_update_by_stack(nd_router_setup_t *nd_router_configuration);
00074 static void border_router_free(protocol_interface_info_entry_t *cur);
00075 
00076 void arm_nwk_6lowpan_borderrouter_data_free(protocol_interface_info_entry_t *cur)
00077 {
00078     if (cur->border_router_setup) {
00079         if (cur->border_router_setup->nd_nwk) {
00080             icmp_nd_border_router_release(cur->border_router_setup->nd_nwk);
00081             ns_dyn_mem_free(cur->border_router_setup->nd_nwk);
00082         }
00083         if (cur->border_router_setup->nd_border_router_configure) {
00084             ns_dyn_mem_free(cur->border_router_setup->nd_border_router_configure);
00085         }
00086         ns_dyn_mem_free(cur->border_router_setup);
00087         cur->border_router_setup = 0;
00088     }
00089 }
00090 
00091 void nd_border_router_setup_refresh(nwk_interface_id id, bool fresh_abro)
00092 {
00093     uint8_t *ptr = 0;
00094     nd_router_t *nd_router_object;
00095     nd_router_setup_t *nd_configure;
00096     protocol_interface_info_entry_t *cur_interface;
00097     uint8_t nd_options[30];
00098 
00099     cur_interface = protocol_stack_interface_info_get(id);
00100     if (!cur_interface) {
00101         return;
00102     } else if (cur_interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00103         return;
00104     } else if (cur_interface->border_router_setup == 0) {
00105         return;
00106     } else if (!cur_interface->border_router_setup->nd_nwk) {
00107         return;
00108     } else if (!cur_interface->border_router_setup->nd_border_router_configure) {
00109         return;
00110     }
00111 
00112     nd_router_object = cur_interface->border_router_setup->nd_nwk;
00113     nd_configure = cur_interface->border_router_setup->nd_border_router_configure;
00114     nd_router_object->life_time = nd_configure->life_time;
00115 
00116     if (!ns_list_is_empty(&nd_router_object->prefix_list)) {
00117         tr_debug("Release Prefix\n");
00118         icmpv6_prefix_list_free(&nd_router_object->prefix_list);
00119     }
00120 
00121     if (!ns_list_is_empty(&nd_router_object->context_list)) {
00122         tr_info("Release Context");
00123         lowpan_context_list_free(&nd_router_object->context_list);
00124     }
00125 
00126     if (!ns_list_is_empty(&nd_configure->context_list)) {
00127         tr_info("Refresh Contexts");
00128         ns_list_foreach(lowpan_context_t, cur, &nd_configure->context_list) {
00129             uint8_t cid_flags = cur->cid | (cur->compression ? LOWPAN_CONTEXT_C : 0);
00130             uint16_t lifetime_mins = (cur->lifetime + 599) / 600;
00131             /* Update contexts in our ABRO advertising storage */
00132             lowpan_context_update(&nd_router_object->context_list, cid_flags, lifetime_mins, cur->prefix, cur->length, true);
00133             /* And contexts used by the interface itself (we don't hear our own adverts) */
00134             lowpan_context_update(&cur_interface->lowpan_contexts, cid_flags, lifetime_mins, cur->prefix, cur->length, true);
00135         }
00136     }
00137     /* Set Prefixs */
00138     if (!ns_list_is_empty(&nd_configure->prefix_list)) {
00139         tr_info("Refresh Prefixs");
00140         ns_list_foreach(prefix_entry_t, cur, &nd_configure->prefix_list) {
00141             ptr = nd_options;
00142             *ptr++ = cur->prefix_len; //Prefix Len
00143             *ptr++ = cur->options;   //Autonomous address enabled
00144             ptr = common_write_32_bit(cur->lifetime, ptr);
00145             ptr = common_write_32_bit(cur->preftime, ptr);
00146             ptr = common_write_32_bit(0, ptr); //Reserved
00147 
00148             memcpy(ptr, cur->prefix, 16);
00149             icmp_nd_router_prefix_update(nd_options, nd_router_object, cur_interface);
00150         }
00151     }
00152 
00153     //Update version num
00154 
00155     if (fresh_abro) {
00156         if (border_router_nd_abro_periodically_update_by_stack(nd_configure) == 0) {
00157             tr_info("ABRO Update and NVM operation OK");
00158         }
00159     }
00160 
00161     nd_router_object->abro_version_num = nd_configure->abro_version_num;
00162 }
00163 
00164 int8_t arm_nwk_6lowpan_border_route_nd_default_prefix_timeout_set(int8_t interface_id, uint32_t time)
00165 {
00166     int8_t ret_val = -1;
00167     protocol_interface_info_entry_t *cur = 0;
00168     cur = protocol_stack_interface_info_get_by_id(interface_id);
00169     if (cur) {
00170         uint8_t *nd_options = ns_dyn_mem_temporary_alloc(30);
00171         if (nd_options) {
00172             uint8_t *ptr;
00173             ptr = nd_options;
00174 
00175             ptr = common_write_16_bit(0x4040, ptr); //Prefix Len + Autonomous address enabled
00176             ptr = common_write_32_bit(time, ptr);
00177             ptr = common_write_32_bit(time, ptr);
00178             memcpy(ptr, cur->border_router_setup->border_router_gp_adr, 8);
00179             ptr += 8;
00180             memset(ptr, 0, 8);
00181             ret_val = icmp_nd_router_prefix_proxy_update(nd_options, cur->border_router_setup->nd_border_router_configure);
00182             ns_dyn_mem_free(nd_options);
00183         }
00184     }
00185     return ret_val;
00186 }
00187 
00188 int8_t arm_nwk_6lowpan_border_router_context_update(int8_t interface_id, uint8_t c_id_flags, uint8_t context_len, uint16_t ttl, const uint8_t *context_ptr)
00189 {
00190     int8_t ret_val = -2;
00191     protocol_interface_info_entry_t *cur = 0;
00192     cur = protocol_stack_interface_info_get_by_id(interface_id);
00193     if (cur) {
00194         ret_val = 0;
00195         if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00196             ret_val = -4;
00197         } else if (cur->border_router_setup == 0) {
00198             ret_val = -3;
00199         } else {
00200             if (c_id_flags < 0x20 && context_len >= 64) {
00201                 if (cur->border_router_setup->nd_nwk) {
00202                     nd_router_setup_t *routerSetup = cur->border_router_setup->nd_border_router_configure;
00203 
00204                     if (!lowpan_contex_get_by_id(&routerSetup->context_list, (c_id_flags & LOWPAN_CONTEXT_CID_MASK))) {
00205                         if (ns_list_count(&routerSetup->context_list) >= ND_MAX_PROXY_CONTEXT_COUNT) {
00206                             return -1;
00207                         }
00208                     }
00209 
00210                     if (lowpan_context_update(&routerSetup->context_list, c_id_flags, ttl, context_ptr, context_len, true) != 0) {
00211                         ret_val = -2;
00212                     } else {
00213                         ret_val = 0;
00214                     }
00215                 }
00216             } else {
00217                 ret_val = -3;
00218             }
00219         }
00220     }
00221     return ret_val;
00222 }
00223 
00224 int8_t arm_nwk_6lowpan_border_router_nd_context_load(int8_t interface_id, uint8_t *contex_data)
00225 {
00226     int8_t ret_val = -2;
00227     protocol_interface_info_entry_t *cur = 0;
00228     cur = protocol_stack_interface_info_get_by_id(interface_id);
00229     if (cur) {
00230         ret_val = 0;
00231         if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00232             ret_val = -4;
00233         } else if (cur->border_router_setup == 0) {
00234             ret_val = -3;
00235         } else {
00236             uint8_t c_id;
00237             uint16_t lifetime;
00238             nd_router_setup_t *nd_router_setup;
00239             uint8_t con_len = *contex_data++;
00240 
00241             nd_router_setup = cur->border_router_setup->nd_border_router_configure;
00242 
00243             c_id = *contex_data++ & 0x1f; // ignore reserved fields
00244             lifetime = common_read_16_bit(contex_data);
00245             contex_data += 2;
00246             //Now Pointer Indicate to prefix
00247             //Check first is current ID at list
00248             if (!lowpan_contex_get_by_id(&nd_router_setup->context_list, (c_id & LOWPAN_CONTEXT_CID_MASK))) {
00249                 if (ns_list_count(&nd_router_setup->context_list) >= ND_MAX_PROXY_CONTEXT_COUNT) {
00250                     tr_debug("All Contexts are allocated");
00251                     return -1;
00252                 }
00253             }
00254             return lowpan_context_update(&nd_router_setup->context_list, c_id, lifetime, contex_data, con_len, true);
00255 
00256         }
00257     }
00258     return ret_val;
00259 }
00260 
00261 
00262 //int8_t border_router_nd_configure_update(void)
00263 int8_t arm_nwk_6lowpan_border_router_configure_push(int8_t interface_id)
00264 {
00265     int8_t ret_val = -1;
00266     protocol_interface_info_entry_t *cur_interface;
00267     cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
00268     if (cur_interface) {
00269         ret_val = 0;
00270         if (cur_interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00271             ret_val = -4;
00272         } else if (cur_interface->border_router_setup == 0) {
00273             ret_val = -3;
00274         } else if ((cur_interface->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
00275             ret_val = -2;
00276         } else {
00277             if (thread_info(cur_interface) == NULL) {
00278                 cur_interface->border_router_setup->nd_nwk->nd_timer = 1;
00279                 cur_interface->border_router_setup->nd_nwk->nd_re_validate = 1;
00280                 cur_interface->border_router_setup->nd_nwk->abro_version_num++;
00281                 ret_val = 0;
00282             }
00283         }
00284     }
00285     return ret_val;
00286 }
00287 
00288 int8_t arm_nwk_6lowpan_border_router_context_remove_by_id(int8_t interface_id, uint8_t c_id)
00289 {
00290     lowpan_context_t *entry;
00291     protocol_interface_info_entry_t *cur_interface = 0;
00292     nd_router_setup_t *nd_router_configuration = 0;
00293     cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
00294     if (!cur_interface) {
00295         return -1;
00296     }
00297 
00298     if (cur_interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00299         return -4;
00300     }
00301 
00302     if (cur_interface->border_router_setup == 0) {
00303         return -3;
00304     }
00305 
00306     nd_router_configuration = cur_interface->border_router_setup->nd_border_router_configure;
00307 
00308     entry = lowpan_contex_get_by_id(&nd_router_configuration->context_list, c_id);
00309     if (entry) {
00310         ns_list_remove(&nd_router_configuration->context_list, entry);
00311         ns_dyn_mem_free(entry);
00312     }
00313     return 0;
00314 }
00315 
00316 int8_t arm_nwk_6lowpan_border_router_context_parameter_update(int8_t interface_id, uint8_t c_id, uint8_t compress_mode, uint16_t ttl)
00317 {
00318     protocol_interface_info_entry_t *cur_interface;
00319     nd_router_setup_t *nd_router_configuration;
00320     lowpan_context_t *entry;
00321     cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
00322     if (!cur_interface) {
00323         return -1;
00324     }
00325 
00326     if (cur_interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00327         return -4;
00328     }
00329 
00330     if (cur_interface->border_router_setup == 0) {
00331         return -3;
00332     }
00333 
00334     nd_router_configuration = cur_interface->border_router_setup->nd_border_router_configure;
00335 
00336     entry = lowpan_contex_get_by_id(&nd_router_configuration->context_list, c_id);
00337     if (entry) {
00338         uint8_t cid_flag = entry->cid;
00339         entry->compression = compress_mode;
00340         entry->lifetime = ttl;
00341         cid_flag |= (entry->compression ? LOWPAN_CONTEXT_C : 0);
00342         return 0;
00343     }
00344     return -1;
00345 }
00346 
00347 int8_t arm_nwk_6lowpan_border_router_init(int8_t interface_id, const border_router_setup_s *border_router_setup_ptr)
00348 {
00349     int8_t ret_val = -3;
00350     protocol_interface_info_entry_t *cur = 0;
00351     nd_router_setup_t *nd_router_configuration = 0;
00352     cur = protocol_stack_interface_info_get_by_id(interface_id);
00353     if (cur) {
00354         ret_val = 0;
00355         if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00356             ret_val = -4;
00357         } else if (cur->border_router_setup == 0) {
00358             ret_val = -3;
00359         } else if (thread_info(cur)) {
00360             ret_val = -5;
00361         } else if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) ==  0) {
00362             uint8_t *ptr = cur->border_router_setup->border_router_gp_adr;
00363             memcpy(ptr, border_router_setup_ptr->lowpan_nd_prefix, 8);
00364             ptr += 8;
00365             cur->border_router_setup->mac_short_adr = border_router_setup_ptr->mac_short_adr;
00366             if (border_router_setup_ptr->mac_short_adr < 0xfffe) {
00367                 cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
00368                 mac_helper_mac16_address_set(cur, border_router_setup_ptr->mac_short_adr);
00369                 memcpy(ptr, ADDR_SHORT_ADR_SUFFIC, 6);
00370                 ptr += 6;
00371                 ptr = common_write_16_bit(cur->border_router_setup->mac_short_adr, ptr);
00372             } else {
00373                 memcpy(ptr, cur->iid_eui64, 8);
00374                 cur->lowpan_address_mode = NET_6LOWPAN_GP64_ADDRESS;
00375             }
00376 
00377             nd_router_configuration = cur->border_router_setup->nd_border_router_configure;
00378 
00379             nd_router_configuration->life_time =  border_router_setup_ptr->ra_life_time;
00380             nd_router_configuration->abro_version_num = border_router_setup_ptr->abro_version_num;
00381             cur->configure_flags |= INTERFACE_ND_BORDER_ROUTER_DEFINED;
00382         } else {
00383             ret_val = -1;
00384         }
00385 
00386         if (ret_val == 0) {
00387             uint8_t *nd_options  = 0;
00388             uint8_t *beaon_payload = 0;
00389 
00390             //Check here FHSS Pointer Hox Hoxs
00391             beaon_payload = mac_helper_beacon_payload_reallocate(cur, 18);
00392 
00393             cur->border_router_setup->mac_panid = border_router_setup_ptr->mac_panid;
00394 
00395             if (beaon_payload == NULL) {
00396                 ret_val = -2;
00397             } else {
00398                 *beaon_payload++ = border_router_setup_ptr->beacon_protocol_id;
00399                 *beaon_payload++ = 7; //Accept Join / Host & Router
00400                 memcpy(beaon_payload, border_router_setup_ptr->network_id, 16);
00401 
00402                 if (mac_helper_beacon_payload_register(cur) != 0) {
00403                     tr_error("Beacon payload register Fail");
00404                 }
00405 
00406                 nd_options  = ns_dyn_mem_temporary_alloc(30);
00407                 if (nd_options) {
00408                     uint8_t *ptr = cur->border_router_setup->nd_nwk->border_router;
00409                     nd_router_base_init(cur->border_router_setup->nd_nwk);
00410 
00411 
00412                     cur->border_router_setup->nd_nwk->nd_state = ND_BR_READY;
00413                     cur->border_router_setup->nd_nwk->nwk_id = IF_6LoWPAN;
00414                     cur->border_router_setup->nd_nwk->life_time = border_router_setup_ptr->ra_life_time;
00415                     memcpy(cur->border_router_setup->nd_nwk->border_router, cur->border_router_setup->border_router_gp_adr, 16);
00416                     if (border_router_setup_ptr->mac_short_adr < 0xfffe) {
00417                         cur->border_router_setup->mac_short_adr = border_router_setup_ptr->mac_short_adr;
00418                     } else {
00419                         cur->border_router_setup->mac_short_adr = 0xffff;
00420                     }
00421 
00422                     //Create GP64
00423                     if (ret_val == 0) {
00424                         ptr = nd_options;
00425                         *ptr++ = 64;//Prefix Len
00426                         *ptr++ = PIO_A; //Autonomous address enabled
00427                         memset(ptr, 0xff, 8);/* Valid Life time & Valid Preferred Life time  0xffffff */
00428                         ptr += 8;
00429                         memcpy(ptr, border_router_setup_ptr->lowpan_nd_prefix, 8);
00430                         ptr += 8;
00431                         memset(ptr, 0, 8);
00432                         ret_val = icmp_nd_router_prefix_proxy_update(nd_options, nd_router_configuration);
00433 
00434                         //Default Prefix TO ND
00435                     }
00436                     if (ret_val == 0) {
00437                         //Context
00438                         if (lowpan_context_update(&nd_router_configuration->context_list, (LOWPAN_CONTEXT_C | 0), (24 * 60), border_router_setup_ptr->lowpan_nd_prefix, 64, true) != 0) {
00439                             ret_val = -2;
00440                         }
00441                     }
00442 
00443                     ns_dyn_mem_free(nd_options);
00444                     if (ret_val == 0) {
00445                         tr_info("BR nwk base ready for start");
00446                     }
00447                 } else {
00448                     ret_val = -2;
00449                 }
00450             }
00451 
00452             if (ret_val == -2) {
00453                 if (cur) {
00454                     border_router_free(cur);
00455                 }
00456             }
00457         }
00458     }
00459     return ret_val;
00460 }
00461 
00462 static void border_router_free(protocol_interface_info_entry_t *cur)
00463 {
00464     if (cur->border_router_setup) {
00465         if (cur->border_router_setup->nd_nwk) {
00466             icmp_nd_router_object_reset(cur->border_router_setup->nd_nwk);
00467             ns_dyn_mem_free(cur->border_router_setup->nd_nwk);
00468         }
00469 
00470 
00471         if (cur->border_router_setup->nd_border_router_configure) {
00472             icmpv6_prefix_list_free(&cur->border_router_setup->nd_border_router_configure->prefix_list);
00473             lowpan_context_list_free(&cur->border_router_setup->nd_border_router_configure->context_list);
00474         }
00475         ns_dyn_mem_free(cur->border_router_setup);
00476         cur->border_router_setup = 0;
00477     }
00478 }
00479 
00480 static int8_t border_router_nd_abro_periodically_update_by_stack(nd_router_setup_t *nd_router_configuration)
00481 {
00482     int8_t ret_val = -1;
00483     if (nd_router_configuration) {
00484         nd_router_configuration->abro_version_num++;
00485         ret_val = 0;
00486     }
00487     return ret_val;
00488 }
00489 
00490 void border_router_start(protocol_interface_info_entry_t *cur, bool warm_link_restart)
00491 {
00492     nd_router_t *nd_nwk = cur->border_router_setup->nd_nwk;
00493     mlme_start_t start_req;
00494     memset(&start_req, 0, sizeof(mlme_start_t));
00495     start_req.PANId = cur->border_router_setup->mac_panid;
00496     start_req.LogicalChannel = cur->mac_parameters->mac_channel;
00497     start_req.ChannelPage = 0;
00498     start_req.BeaconOrder = 0x0f;
00499     start_req.SuperframeOrder = 0x0f;
00500     start_req.PANCoordinator = 1;
00501     if (cur->mac_api) {
00502         protocol_timer_start(PROTOCOL_TIMER_BOOTSTRAP_TIM, bootstrap_timer_handle, BOOTSTRAP_START_TIMEOUT);
00503         cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void *)&start_req);
00504     }
00505     if (warm_link_restart) {
00506         return;
00507     }
00508     mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
00509 #ifndef NO_MLE
00510     blacklist_clear();
00511 #endif
00512 
00513     cur->border_router_setup->initActive = true;
00514 
00515     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
00516     addr_interface_set_ll64(cur, NULL);
00517     cur->interface_mode = INTERFACE_UP;
00518     cur->nwk_mode = ARM_NWK_GP_IP_MODE;
00519     if (nd_nwk) {
00520         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
00521             protocol_6lowpan_router_synch_to_new_router(cur, NULL, 0, true);
00522             cur->bootsrap_state_machine_cnt = 30;
00523         } else {
00524             nd_nwk->mle_advert_timer = 0;
00525             cur->bootsrap_state_machine_cnt = 1;
00526         }
00527         cur->nwk_bootstrap_state = ER_SCAN;
00528         whiteboard_interface_register(nd_nwk->border_router, cur->id);
00529         cur->nwk_nd_re_scan_count = 2;
00530 
00531     } else {
00532         thread_interface_up(cur);
00533         rpl_control_remove_domain_from_interface(cur);
00534         nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
00535     }
00536 }
00537 
00538 static int arm_mac_channel_list_analyze(protocol_interface_info_entry_t *cur)
00539 {
00540     int number_of_channels = 0;
00541     for (int i = 0; i < 8; i++) {
00542         for (int j = 0; j < 4; j++) {
00543             number_of_channels += common_count_bits((uint8_t)(cur->mac_parameters->mac_channel_list.channel_mask[i] >> (j * 8)));
00544         }
00545     }
00546     return number_of_channels;
00547 }
00548 
00549 static int8_t arm_border_router_interface_up(protocol_interface_info_entry_t *cur)
00550 {
00551     bool warm_restart = false;
00552     if (cur->interface_mode == INTERFACE_UP || cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00553         //Disable interface like starting normal scan request
00554         if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE) {
00555             return -4;
00556         }
00557         warm_restart = true;
00558         tr_debug("Do warm link start");
00559     } else {
00560         nd_router_t *nd_nwk = cur->border_router_setup->nd_nwk;
00561         //SET SHort Address
00562         if (cur->border_router_setup->mac_short_adr < 0xfffe) {
00563             mac_helper_mac16_address_set(cur, cur->border_router_setup->mac_short_adr);
00564             cur->lowpan_desired_short_address = cur->border_router_setup->mac_short_adr;
00565             protocol_6lowpan_set_ll16(cur, cur->border_router_setup->mac_short_adr);
00566         }
00567         mac_helper_panid_set(cur, cur->border_router_setup->mac_panid);
00568 
00569         if (cur->nwk_wpan_nvm_api) {
00570             wpan_nvm_params_t *params = cur->nwk_wpan_nvm_api->nvm_params_get_cb(cur->nwk_wpan_nvm_api, cur->border_router_setup->mac_panid);
00571             cur->if_lowpan_security_params->mle_security_frame_counter = params->mle_securit_counter;
00572             //SET MAC and MLE security frame counters
00573             mle_service_security_set_frame_counter(cur->id, params->mle_securit_counter);
00574             mac_helper_link_frame_counter_set(cur->id, params->mac_security_frame_counter);
00575         }
00576 
00577         // cur->mac_channel = cur->border_router_setup->channel;
00578         if (nd_nwk) {
00579             nd_border_router_setup_refresh(nd_nwk->nwk_id, false);
00580         }
00581         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER;
00582         icmpv6_recv_ra_routes(cur, false);
00583         protocol_6lowpan_interface_common_init(cur);
00584 
00585         mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
00586         mac_helper_pib_boolean_set(cur, macAssociationPermit, true);
00587 
00588         arm_6lowpan_security_init_ifup(cur);
00589 
00590         mac_helper_default_security_level_set(cur, cur->mac_parameters->mac_configured_sec_level);
00591 
00592         //set 6lowpan default
00593         mac_helper_mac_mlme_max_retry_set(cur->id, LOWPAN_MAX_FRAME_RETRIES);
00594 
00595         if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
00596             if (pana_server_key_material_load(cur->id) != 0) {
00597                 tr_warn("Border router security load fail");
00598                 return -3;
00599             }
00600         }
00601     }
00602 
00603     int number_of_channels = arm_mac_channel_list_analyze(cur);
00604     cur->lowpan_info |= INTERFACE_NWK_ACTIVE;
00605 
00606     /* Start network scan when at least 2 of 256 channels are enabled,
00607      * otherwise MAC is started immediately.
00608      */
00609     if (number_of_channels > 1) {
00610         if (warm_restart) {
00611             bootsrap_next_state_kick(ER_WARM_ACTIVE_SCAN, cur);
00612         } else {
00613             bootsrap_next_state_kick(ER_ACTIVE_SCAN, cur);
00614         }
00615     } else {
00616         border_router_start(cur, warm_restart);
00617     }
00618     return 0;
00619 }
00620 
00621 static int arm_border_router_proxy_validate(int8_t interface_id, uint8_t *address)
00622 {
00623 
00624     /* Could also check route type, but I don't think it really matters */
00625     ipv6_route_t *route;
00626     route = ipv6_route_choose_next_hop(address, interface_id, NULL);
00627     if (!route || route->prefix_len < 128) {
00628         return -1;
00629     }
00630 
00631     return 0;
00632 }
00633 
00634 int arm_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handler_interface_id, bool status)
00635 {
00636     (void)caller_interface_id;
00637 
00638     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id);
00639     if (!cur) {
00640         tr_error("No Interface");
00641         return -1;
00642     }
00643 
00644     if (status) {
00645         tr_debug("Border router Backhaul link ready");
00646     } else {
00647         tr_debug("Border router Backhaul link down");
00648     }
00649     return 0;
00650 }
00651 
00652 void arm_border_router_ready(protocol_interface_info_entry_t *cur)
00653 {
00654     if (cur->border_router_setup) {
00655         nd_router_t *nd_nwk = cur->border_router_setup->nd_nwk;
00656         if (nd_nwk) {
00657             addr_add_router_groups(cur);
00658             addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS);
00659             icmpv6_radv_enable(cur);
00660 
00661             if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
00662                 nd_nwk->mle_advert_timer = 50;
00663             }
00664 
00665             nd_nwk->nd_re_validate = nd_nwk->life_time;
00666             nd_nwk->nd_re_validate /= 4;
00667             nd_nwk->nd_re_validate *= 3;
00668             nd_nwk->nd_timer = 10;
00669             nd_set_br(nd_nwk);
00670             icmpv6_restart_router_advertisements(cur, nd_nwk->border_router);
00671             rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
00672             cur->border_router_setup->initActive = false;
00673 
00674             //SET Interface Default address
00675             cur->global_address_available = true;
00676             ipv6_prefix_on_link_update(nd_nwk->border_router);
00677 
00678         }
00679         //Updates beacon contents
00680         beacon_join_priority_update(cur->id);
00681 
00682         cur->bootsrap_state_machine_cnt = 0;
00683         cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
00684         net_load_balance_internal_state_activate(cur, true);
00685         nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur);
00686         nd_proxy_downstream_interface_register(cur->id, arm_border_router_proxy_validate, arm_border_router_proxy_state_update);
00687     }
00688 }
00689 
00690 static int8_t arm_border_router_interface_down(protocol_interface_info_entry_t *cur)
00691 {
00692     int8_t ret_val = 0;
00693     nd_router_t *nd_nwk = cur->border_router_setup->nd_nwk;
00694     /* Change Active -> Idle */
00695     /* Disable Protocols Timers */
00696     tr_info("BR-->IDLE");
00697     neighbor_cache_flush(&cur->neigh_cache);
00698 
00699     mlme_reset_t reset;
00700     reset.SetDefaultPIB = true;
00701     cur->mac_api->mlme_req(cur->mac_api, MLME_RESET, &reset);
00702 
00703     net_load_balance_internal_state_activate(cur, false);
00704     whiteboard_interface_unregister_all_address(cur->id);
00705     if (cur->nwk_wpan_nvm_api) {
00706         cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
00707     }
00708     cur->if_lowpan_security_params->mle_security_frame_counter = mle_service_security_get_frame_counter(cur->id);
00709     mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
00710 #ifndef NO_MLE
00711     blacklist_clear();
00712 #endif
00713     if (nd_nwk) {
00714         ipv6_prefix_on_link_remove(nd_nwk->border_router);
00715         icmp_nd_border_router_release(nd_nwk);
00716     }
00717 
00718     //MAC
00719     mac_helper_link_frame_counter_set(cur->id, 0);
00720     mac_helper_panid_set(cur, 0xffff);
00721     mac_helper_mac16_address_set(cur, 0xffff);
00722     /* Init RPL Timers */
00723 
00724     cur->lowpan_info &= ~INTERFACE_NWK_ACTIVE;
00725     mac_helper_default_security_level_set(cur, SEC_NONE);
00726     //Reset WhiteBoard
00727     whiteboard_init(cur->id);
00728     lowpan_adaptation_interface_reset(cur->id);
00729     reassembly_interface_reset(cur->id);
00730     protocol_core_interface_info_reset(cur);
00731     cur->bootsrap_state_machine_cnt = 0;
00732     cur->interface_mode = INTERFACE_IDLE;
00733     nd_proxy_downstream_interface_unregister(cur->id);
00734     return ret_val;
00735 }
00736 
00737 int8_t arm_nwk_6lowpan_borderrouter_init(protocol_interface_info_entry_t *cur)
00738 {
00739     /* Border Router Allocate entry */
00740     if (cur->border_router_setup == 0) {
00741         cur->border_router_setup = ns_dyn_mem_alloc(sizeof(br_info_t));
00742         if (!cur->border_router_setup) {
00743             return -1;
00744 
00745         }
00746         cur->border_router_setup->nd_nwk = ns_dyn_mem_alloc(sizeof(nd_router_t));
00747         cur->border_router_setup->nd_border_router_configure = ns_dyn_mem_alloc(sizeof(nd_router_setup_t));
00748 
00749         if (cur->border_router_setup->nd_nwk == 0 || cur->border_router_setup->nd_border_router_configure == 0) {
00750             arm_nwk_6lowpan_borderrouter_data_free(cur);
00751         }
00752         if (cur->border_router_setup) {
00753             cur->border_router_setup->mac_short_adr = 0xffff;
00754             cur->border_router_setup->mac_panid = 0xffff;
00755             if (cur->border_router_setup->nd_border_router_configure) {
00756                 ns_list_init(&cur->border_router_setup->nd_border_router_configure->prefix_list);
00757                 ns_list_init(&cur->border_router_setup->nd_border_router_configure->context_list);
00758             }
00759         }
00760 
00761     } else {
00762         if (cur->border_router_setup->nd_nwk) {
00763             //Clear Setup
00764             nd_router_t *router_object = cur->border_router_setup->nd_nwk;
00765             /**
00766              * Reset Current ND Setup
00767              */
00768             icmp_nd_router_object_reset(router_object);
00769         }
00770     }
00771     whiteboard_init(cur->id);
00772     cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER;
00773     cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
00774     cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
00775     cur->if_up = arm_border_router_interface_up;
00776     cur->if_down = arm_border_router_interface_down;
00777     return 0;
00778 }
00779 
00780 #else
00781 
00782 int8_t arm_nwk_6lowpan_border_router_init(int8_t interface_id, const border_router_setup_s *border_router_setup_ptr)
00783 {
00784     (void) interface_id;
00785     (void) border_router_setup_ptr;
00786     return -3;
00787 }
00788 
00789 int8_t arm_nwk_6lowpan_border_router_context_parameter_update(int8_t interface_id, uint8_t c_id,
00790                                                               uint8_t compress_mode, uint16_t ttl)
00791 {
00792     (void) interface_id;
00793     (void) c_id;
00794     (void) compress_mode;
00795     (void) ttl;
00796     return -1;
00797 }
00798 
00799 int8_t arm_nwk_6lowpan_border_router_context_remove_by_id(int8_t interface_id, uint8_t c_id)
00800 {
00801     (void) interface_id;
00802     (void) c_id;
00803     return -1;
00804 }
00805 
00806 int8_t arm_nwk_6lowpan_border_router_configure_push(int8_t interface_id)
00807 {
00808     (void) interface_id;
00809     return -1;
00810 }
00811 
00812 int8_t arm_nwk_6lowpan_border_router_nd_context_load(int8_t interface_id, uint8_t *contex_data)
00813 {
00814     (void) interface_id;
00815     (void) contex_data;
00816     return -1;
00817 }
00818 
00819 int8_t arm_nwk_6lowpan_border_router_context_update(int8_t interface_id, uint8_t c_id_flags, uint8_t context_len, uint16_t ttl, const uint8_t *context_ptr)
00820 {
00821     (void) interface_id;
00822     (void) c_id_flags;
00823     (void) context_len;
00824     (void) ttl;
00825     (void) context_ptr;
00826     return -1;
00827 }
00828 
00829 int8_t arm_nwk_6lowpan_border_route_nd_default_prefix_timeout_set(int8_t interface_id, uint32_t time)
00830 {
00831     (void) interface_id;
00832     (void) time;
00833     return -1;
00834 }
00835 
00836 #endif