Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_bbr_api.c Source File

ws_bbr_api.c

00001 /*
00002  * Copyright (c) 2018-2019, 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 <string.h>
00019 #include "nsconfig.h"
00020 #include "ns_types.h"
00021 #include "ns_trace.h"
00022 #include "net_interface.h"
00023 #include "eventOS_event.h"
00024 #include "NWK_INTERFACE/Include/protocol.h"
00025 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00026 #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
00027 #include "6LoWPAN/ws/ws_config.h"
00028 #include "6LoWPAN/ws/ws_common.h"
00029 #include "6LoWPAN/ws/ws_bootstrap.h"
00030 #include "RPL/rpl_control.h"
00031 #include "RPL/rpl_data.h"
00032 #include "Common_Protocols/icmpv6.h"
00033 #include "Common_Protocols/icmpv6_radv.h"
00034 #include "ws_management_api.h"
00035 #include "net_rpl.h"
00036 #include "Service_Libs/nd_proxy/nd_proxy.h"
00037 #include "6LoWPAN/ws/ws_bbr_api_internal.h"
00038 #include "6LoWPAN/ws/ws_pae_controller.h"
00039 #include "DHCPv6_Server/DHCPv6_server_service.h"
00040 #include "DHCPv6_client/dhcpv6_client_api.h"
00041 
00042 #include "ws_bbr_api.h"
00043 
00044 #define TRACE_GROUP "BBRw"
00045 
00046 #define RPL_INSTANCE_ID 1
00047 
00048 static uint8_t current_instance_id = RPL_INSTANCE_ID;
00049 
00050 #ifdef HAVE_WS_BORDER_ROUTER
00051 
00052 #define WS_ULA_LIFETIME 24*3600
00053 #define WS_ROUTE_LIFETIME WS_ULA_LIFETIME
00054 #define WS_DHCP_ADDRESS_LIFETIME 2*3600
00055 #define BBR_CHECK_INTERVAL 60
00056 #define BBR_BACKUP_ULA_DELAY 300
00057 
00058 /* when creating BBR make ULA dodag ID always and when network becomes available add prefix to DHCP
00059  *
00060  *
00061  */
00062 static int8_t backbone_interface_id = -1; // BBR backbone information
00063 static uint16_t configuration = 0;
00064 
00065 static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x72, 0x83, 0x7e};
00066 static uint8_t static_dodag_id_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
00067 static uint8_t current_dodag_id[16] = {0};
00068 static uint8_t current_local_prefix[8] = {0};
00069 static uint8_t current_global_prefix[8] = {0};
00070 static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
00071 static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
00072 
00073 static rpl_dodag_conf_t rpl_conf = {
00074     // Lifetime values
00075     .default_lifetime = 120,
00076     .lifetime_unit = 60,
00077     .objective_code_point = 1, // MRHOF algorithm used
00078     .authentication = false,
00079     .path_control_size = 7,
00080     .dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE,
00081     .min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE,
00082     // DIO configuration
00083     .dio_interval_min = WS_RPL_DIO_IMIN,
00084     .dio_interval_doublings = WS_RPL_DIO_DOUBLING,
00085     .dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY
00086 };
00087 
00088 void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase)
00089 {
00090     if (imin == 0 || doubling == 0) {
00091         // use default values
00092         imin = WS_RPL_DIO_IMIN;
00093         doubling = WS_RPL_DIO_DOUBLING;
00094         redundancy = WS_RPL_DIO_REDUNDANCY;
00095     }
00096 
00097     if (rpl_conf.dio_interval_min == imin &&
00098             rpl_conf.dio_interval_doublings == doubling &&
00099             rpl_conf.dio_redundancy_constant == redundancy &&
00100             rpl_conf.dag_max_rank_increase == dag_max_rank_increase &&
00101             rpl_conf.min_hop_rank_increase == min_hop_rank_increase) {
00102         // Same values no update needed
00103         return;
00104     }
00105 
00106     rpl_conf.dio_interval_min = imin;
00107     rpl_conf.dio_interval_doublings = doubling;
00108     rpl_conf.dio_redundancy_constant = redundancy;
00109     rpl_conf.dag_max_rank_increase = dag_max_rank_increase;
00110     rpl_conf.min_hop_rank_increase = min_hop_rank_increase;
00111 
00112     if (protocol_6lowpan_rpl_root_dodag) {
00113         rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf);
00114         rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
00115     }
00116 }
00117 
00118 static void ws_bbr_rpl_root_start(uint8_t *dodag_id)
00119 {
00120     tr_info("RPL root start");
00121     rpl_data_init_root();
00122 
00123     if (protocol_6lowpan_rpl_root_dodag) {
00124         rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
00125         protocol_6lowpan_rpl_root_dodag = NULL;
00126         current_instance_id++;
00127     }
00128 
00129     protocol_6lowpan_rpl_root_dodag = rpl_control_create_dodag_root(protocol_6lowpan_rpl_domain, current_instance_id, dodag_id, &rpl_conf, rpl_conf.min_hop_rank_increase, RPL_GROUNDED | RPL_MODE_NON_STORING | RPL_DODAG_PREF(0));
00130     if (!protocol_6lowpan_rpl_root_dodag) {
00131         tr_err("RPL dodag init failed");
00132         return;
00133     }
00134     // RPL memory limits set larger for Border router
00135     rpl_control_set_memory_limits(64 * 1024, 0);
00136 }
00137 
00138 static void ws_bbr_rpl_root_stop(void)
00139 {
00140     tr_info("RPL root stop");
00141     if (protocol_6lowpan_rpl_root_dodag) {
00142         rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
00143         protocol_6lowpan_rpl_root_dodag = NULL;
00144         current_instance_id++;
00145     }
00146     memset(current_local_prefix, 0, 8);
00147     memset(current_global_prefix, 0, 8);
00148     memset(current_dodag_id, 0, 16);
00149 }
00150 
00151 static int ws_border_router_proxy_validate(int8_t interface_id, uint8_t *address)
00152 {
00153 
00154     /* Could also check route type, but I don't think it really matters */
00155     ipv6_route_t *route;
00156     route = ipv6_route_choose_next_hop(address, interface_id, NULL);
00157     if (!route || route->prefix_len < 128) {
00158         return -1;
00159     }
00160 
00161     return 0;
00162 }
00163 
00164 int ws_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handler_interface_id, bool status)
00165 {
00166     (void)caller_interface_id;
00167 
00168     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id);
00169     if (!cur) {
00170         tr_error("No Interface");
00171         return -1;
00172     }
00173 
00174     tr_debug("Border router Backhaul link %s", status ? "ready" : "down");
00175     return 0;
00176 }
00177 
00178 static if_address_entry_t *ws_bbr_slaac_generate(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix)
00179 {
00180     if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, ula_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
00181     if (!add_entry) {
00182         tr_err("ula create failed");
00183         return NULL;
00184     }
00185     addr_policy_table_add_entry(ula_prefix, 64, 2, WS_NON_PREFFRED_LABEL);
00186     return add_entry;
00187 }
00188 
00189 static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix)
00190 {
00191     icmpv6_slaac_prefix_update(cur, ula_prefix, 64, 0, 0);
00192     addr_policy_table_delete_entry(ula_prefix, 64);
00193 }
00194 
00195 
00196 static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
00197 {
00198     if (memcmp(current_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
00199         // address generated
00200         return 0;
00201     }
00202     // This address is only used if no other address available.
00203     if_address_entry_t *add_entry = ws_bbr_slaac_generate(cur, static_dodag_id_prefix);
00204     if (!add_entry) {
00205         tr_err("dodagid create failed");
00206         return -1;
00207     }
00208     memcpy(current_dodag_id, add_entry->address, 16);
00209     tr_info("BBR generate DODAGID %s", trace_ipv6(current_dodag_id));
00210 
00211     return 0;
00212 }
00213 
00214 /*
00215  * 0 static non rooted self generated own address
00216  * 1 static address with backbone connectivity
00217  */
00218 static void ws_bbr_bb_static_prefix_get(uint8_t *dodag_id_ptr)
00219 {
00220 
00221     /* Get static ULA prefix if we have configuration in backbone and there is address we use that.
00222      *
00223      * If there is no address we can use our own generated ULA as a backup ULA
00224      */
00225 
00226     protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
00227 
00228     if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00229         if (protocol_address_prefix_cmp(bb_interface, bb_interface->ipv6_configure->static_prefix64, 64)) {
00230             memcpy(dodag_id_ptr, bb_interface->ipv6_configure->static_prefix64, 8);
00231         }
00232     }
00233     return;
00234 }
00235 
00236 
00237 static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_ptr)
00238 {
00239     uint8_t global_address[16];
00240 
00241     memset(global_prefix_ptr, 0, 8);
00242 
00243     // By default static dodagID prefix is used as local prefix
00244     memcpy(local_prefix_ptr, static_dodag_prefix, 8);
00245     ws_bbr_bb_static_prefix_get(local_prefix_ptr);
00246 
00247     if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
00248         // No global prefix available
00249         return;
00250     }
00251     protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
00252     if_address_entry_t *addr_entry = addr_get_entry(bb_interface, global_address);
00253 
00254     if (!addr_entry || addr_entry->preferred_lifetime == 0) {
00255         return;
00256     }
00257     //tr_debug("BBR address %s lifetime %d pref %d", trace_ipv6(addr_entry->address), addr_entry->valid_lifetime, addr_entry->preferred_lifetime);
00258 
00259     if (memcmp(global_address, local_prefix_ptr, 8) == 0) {
00260         // static prefix is same
00261         return;
00262     }
00263     memcpy(global_prefix_ptr, global_address, 8);
00264     return;
00265 }
00266 static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
00267 {
00268     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00269     if (!cur) {
00270         return;
00271     }
00272     // Send NA only if it is enabled for the backhaul
00273     if (!cur->send_na) {
00274         return;
00275     }
00276 
00277     buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
00278     protocol_push(buffer);
00279     return;
00280 
00281 }
00282 
00283 static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src)
00284 {
00285     (void)route_src;
00286     protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId);
00287     if (!curPtr) {
00288         return false;
00289     }
00290 
00291     // When address is allocated we send NA to backbone to notify the new address and flush from other BBRs
00292     wisun_bbr_na_send(backbone_interface_id, address_info->allocatedAddress);
00293     return true;
00294 }
00295 
00296 static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id)
00297 {
00298     uint8_t ll[16];
00299     memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8);
00300     memcpy(&ll[8], cur->mac, 8);
00301     ll[8] ^= 2;
00302 
00303     tr_debug("DHCP server activate %s", trace_ipv6_prefix(global_id, 64));
00304 
00305     if (DHCPv6_server_service_init(cur->id, global_id, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) != 0) {
00306         tr_error("DHCPv6 Server create fail");
00307         return;
00308     }
00309     DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
00310 
00311     DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true);
00312     DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME);
00313 
00314     ws_dhcp_client_address_request(cur, global_id, ll);
00315 }
00316 static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
00317 {
00318     uint8_t temp_address[16];
00319     memcpy(temp_address, global_id, 8);
00320     memset(temp_address + 8, 0, 8);
00321     tr_debug("DHCP server deactivate %s", trace_ipv6(temp_address));
00322     DHCPv6_server_service_delete(cur->id, global_id, false);
00323     //Delete Client
00324     dhcp_client_global_address_delete(cur->id, NULL, temp_address);
00325 
00326 }
00327 
00328 static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
00329 {
00330 
00331     uint8_t local_prefix[8] = {0};
00332     uint8_t global_prefix[8] = {0};
00333 
00334     //tr_info("BBR status check");
00335 
00336     /*
00337      * Start RPL Root
00338      */
00339     if (!protocol_6lowpan_rpl_root_dodag) {
00340         // Generate DODAGID
00341         if (ws_bbr_static_dodagid_create(cur) == 0) {
00342             ws_bbr_rpl_root_start(current_dodag_id);
00343         }
00344     }
00345 
00346     if (!protocol_6lowpan_rpl_root_dodag) {
00347         // Failed to start
00348         tr_err("BBR failed to start");
00349         return;
00350     }
00351 
00352     /*
00353      * Check that DODAGID is still valid
00354      */
00355     if (protocol_interface_address_compare(current_dodag_id) != 0) {
00356         //DODAGID is lost need to restart
00357         tr_warn("DODAGID lost restart RPL");
00358         memset(current_dodag_id, 0, 16);
00359         ws_bbr_rpl_root_stop();
00360         return;
00361     }
00362 
00363     ws_bbr_dodag_get(local_prefix, global_prefix);
00364     tr_debug("BBR global %s, local %s", trace_ipv6_prefix(global_prefix, 64), trace_ipv6_prefix(local_prefix, 64));
00365 
00366     /*
00367      * Add default route to RPL
00368      */
00369     rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, WS_ROUTE_LIFETIME, false);
00370 
00371     /*
00372      * Create static ULA configuration or modify if needed
00373      */
00374     if ((configuration & BBR_ULA_C) &&
00375             memcmp(current_local_prefix, local_prefix, 8) != 0) {
00376         // Generate Static ULA
00377         // Start static ULA prefix and routing always
00378         if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00379             // Remove Old ULA prefix
00380             ws_bbr_slaac_remove(cur, current_local_prefix);
00381             rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_local_prefix, 64, PIO_A, 0, 0, true);
00382             memset(current_local_prefix, 0, 8);
00383         }
00384 
00385         if (memcmp(local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00386             if (!ws_bbr_slaac_generate(cur, local_prefix)) {
00387                 return;
00388             }
00389 
00390             tr_info("RPL Local prefix activate %s", trace_ipv6_prefix(local_prefix, 64));
00391             rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, local_prefix, 64, PIO_A, WS_ULA_LIFETIME, WS_ULA_LIFETIME, false);
00392             memcpy(current_local_prefix, local_prefix, 8);
00393         }
00394     }
00395 
00396     /*
00397      * Check if backup ULA prefix is needed
00398      */
00399     if ((configuration & BBR_ULA_C) == 0 && memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
00400         //Global prefix not available count if backup ULA should be created
00401         global_prefix_unavailable_timer += BBR_CHECK_INTERVAL;
00402         tr_debug("Check for backup prefix %"PRIu32"", global_prefix_unavailable_timer);
00403         if (global_prefix_unavailable_timer >= BBR_BACKUP_ULA_DELAY) {
00404             if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
00405                 tr_info("start using backup prefix %s", trace_ipv6_prefix(local_prefix, 64));
00406             }
00407             memcpy(global_prefix, local_prefix, 8);
00408         }
00409     } else {
00410         //Global connection OK
00411         global_prefix_unavailable_timer = 0;
00412     }
00413 
00414     /*
00415      * Check for Global prefix
00416      */
00417     if (memcmp(current_global_prefix, global_prefix, 8) != 0) {
00418         // Global prefix changed
00419         if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00420             // TODO remove old global prefix
00421             tr_info("RPL global prefix deactivate %s", trace_ipv6_prefix(current_global_prefix, 64));
00422 
00423             // Old backbone information is deleted after 120 seconds
00424             rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, 0, true);
00425             if (configuration & BBR_GUA_ROUTE) {
00426                 rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, true);
00427             }
00428             ipv6_route_add_with_info(current_global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0);
00429 
00430             ws_bbr_dhcp_server_stop(cur, current_global_prefix);
00431         }
00432         // TODO add global prefix
00433         if (memcmp(global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00434 
00435             tr_info("RPL global prefix activate %s", trace_ipv6_prefix(global_prefix, 64));
00436             // Add default route to RPL
00437             // Enable default routing to backbone
00438             if (ipv6_route_add_with_info(global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0) == NULL) {
00439                 tr_err("global route add failed");
00440                 return;
00441             }
00442             ws_bbr_dhcp_server_start(cur, global_prefix);
00443             rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false);
00444             // no check for failure should have
00445 
00446             if (configuration & BBR_GUA_ROUTE) {
00447                 // Add also global prefix and route to RPL
00448                 rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
00449             }
00450 
00451         }
00452         memcpy(current_global_prefix, global_prefix, 8);
00453         rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
00454         nd_proxy_downstream_interface_register(cur->id, ws_border_router_proxy_validate, ws_border_router_proxy_state_update);
00455     } else if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00456         /*
00457          *  This is a keep alive validation RPL is updated to hold the real info.
00458          *  There is no status checks on prefix adds so this makes sure they are not lost
00459          *  DHCP validation should be done also
00460          */
00461         rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, 0, false);
00462 
00463         if (configuration & BBR_GUA_ROUTE) {
00464             // Add also global prefix and route to RPL
00465             rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
00466         }
00467     }
00468 }
00469 
00470 void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
00471 {
00472     (void)seconds;
00473 
00474     if (!ws_info(cur)) {
00475         return;
00476     }
00477     if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
00478         // Not a border router
00479         return;
00480     }
00481     if (!cur->rpl_domain) {
00482         // RPL not started
00483         return;
00484     }
00485 
00486     if (bbr_delay_timer > seconds) {
00487         bbr_delay_timer -= seconds;
00488     } else {
00489         bbr_delay_timer = BBR_CHECK_INTERVAL; // 20 second interval between status checks
00490 
00491         // prequisists
00492         // Wi-SUN network configuration started without RPL
00493 
00494         // RPL configured simple
00495         // 1. Wait for backend connection
00496         // 2. When address becomes available in backend start RPL dodag
00497         // 3. if address removed remove dodag
00498 
00499         // RPL configured Advanced
00500         // 1. Add ULA DODAG and and start ROOT even without backend
00501         //   a. If static prefix configured use it.
00502         //   b. generate random ULA and publish it to backend
00503         // 2. if GUA prefix becomes available in backend add new prefix to DODAG
00504         // 3. if GUA prefix is removed remove the prefix.
00505 
00506         ws_bbr_rpl_status_check(cur);
00507 
00508     }
00509     // Normal BBR operation
00510     if (protocol_6lowpan_rpl_root_dodag) {
00511         if (cur->ws_info->pan_version_timer > seconds) {
00512             cur->ws_info->pan_version_timer -= seconds;
00513         } else {
00514             // Border router has timed out
00515             tr_debug("Border router version number update");
00516             cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config);
00517             cur->ws_info->pan_information.pan_version++;
00518             // Inconsistent for border router to make information distribute faster
00519             ws_bootstrap_configuration_trickle_reset(cur);
00520 
00521             if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
00522                 ws_common_network_size_configure(cur, cur->ws_info->pan_information.pan_size);
00523             }
00524         }
00525 
00526     }
00527 
00528 }
00529 
00530 uint16_t test_pan_size_override = 0xffff;
00531 
00532 uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
00533 {
00534     uint16_t result = 0;
00535     if (test_pan_size_override != 0xffff) {
00536         return test_pan_size_override;
00537     }
00538     //
00539     const uint8_t *prefix_ptr;
00540     if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
00541         //Use GUA Prefix
00542         prefix_ptr = current_global_prefix;
00543     } else {
00544         //Use ULA for indentifier
00545         prefix_ptr = current_local_prefix;
00546     }
00547 
00548     rpl_control_get_instance_dao_target_count(cur->rpl_domain, current_instance_id, NULL, prefix_ptr, &result);
00549     if (result > 0) {
00550         // remove the Border router from the PAN size
00551         result--;
00552     }
00553     return result;
00554 }
00555 
00556 bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur)
00557 {
00558 
00559     (void)cur;
00560     uint8_t global_address[16];
00561 
00562     if (backbone_interface_id < 0) {
00563         // No need to wait for backbone
00564         return true;
00565     }
00566 
00567     if ((configuration & BBR_BB_WAIT) != BBR_BB_WAIT) {
00568         // No need to wait for backbone
00569         return true;
00570     }
00571 
00572     if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
00573         // No global prefix available
00574         return false;
00575     }
00576 
00577     return true;
00578 }
00579 #endif //HAVE_WS_BORDER_ROUTER
00580 
00581 /* Public APIs
00582  *
00583  */
00584 
00585 int ws_bbr_start(int8_t interface_id, int8_t bb_interface_id)
00586 {
00587 #ifdef HAVE_WS_BORDER_ROUTER
00588 
00589     (void)interface_id;
00590     protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(bb_interface_id);
00591 
00592     if (!bb_interface) {
00593         return -1;
00594     }
00595     // TODO make bb configurations
00596 
00597     backbone_interface_id = bb_interface_id;
00598 
00599     return 0;
00600 #else
00601     (void)interface_id;
00602     (void)bb_interface_id;
00603     return -1;
00604 #endif
00605 }
00606 void ws_bbr_stop(int8_t interface_id)
00607 {
00608 #ifdef HAVE_WS_BORDER_ROUTER
00609 
00610     (void)interface_id;
00611     backbone_interface_id = -1;
00612 
00613     if (!protocol_6lowpan_rpl_domain) {
00614         return;
00615     }
00616 
00617     rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
00618     protocol_6lowpan_rpl_root_dodag = NULL;
00619     current_instance_id++;
00620 
00621 #else
00622     (void)interface_id;
00623 #endif
00624 }
00625 int ws_bbr_configure(int8_t interface_id, uint16_t options)
00626 {
00627 #ifdef HAVE_WS_BORDER_ROUTER
00628 
00629     (void)interface_id;
00630     if (protocol_6lowpan_rpl_root_dodag &&
00631             options != configuration) {
00632         //Configuration changed delete previous setup
00633         ws_bbr_rpl_root_stop();
00634     }
00635     configuration = options;
00636     return 0;
00637 #else
00638     (void)interface_id;
00639     (void)options;
00640     return -1;
00641 #endif
00642 }
00643 
00644 int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
00645 {
00646     (void) interface_id;
00647     (void) eui64;
00648 #ifdef HAVE_WS_BORDER_ROUTER
00649     return ws_pae_controller_node_keys_remove(interface_id, eui64);
00650 #else
00651     return -1;
00652 #endif
00653 }
00654 
00655 int ws_bbr_node_access_revoke_start(int8_t interface_id)
00656 {
00657     (void) interface_id;
00658 #ifdef HAVE_WS_BORDER_ROUTER
00659     return ws_pae_controller_node_access_revoke_start(interface_id);
00660 #else
00661     return -1;
00662 #endif
00663 }
00664 
00665 int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit)
00666 {
00667     (void) interface_id;
00668 #ifdef HAVE_WS_BORDER_ROUTER
00669     return ws_pae_controller_node_limit_set(interface_id, limit);
00670 #else
00671     (void) limit;
00672     return -1;
00673 #endif
00674 }
00675 
00676 int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation)
00677 {
00678     (void) interface_id;
00679 #ifdef HAVE_WS_BORDER_ROUTER
00680     bool enabled = false;
00681     if (validation & BBR_CRT_EXT_VALID_WISUN) {
00682         enabled = true;
00683     }
00684     return ws_pae_controller_ext_certificate_validation_set(interface_id, enabled);
00685 #else
00686     (void) validation;
00687     return -1;
00688 #endif
00689 }