Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers net_load_balance.c Source File

net_load_balance.c

00001 /*
00002  * Copyright (c) 2016-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 "nsconfig.h"
00019 #include "ns_types.h"
00020 #include "ns_trace.h"
00021 #include <string.h>
00022 #include "net_load_balance_api.h"
00023 #include "net_interface.h"
00024 #include "NWK_INTERFACE/Include/protocol.h"
00025 #ifdef HAVE_6LOWPAN_ND
00026 #include "net_rpl.h"
00027 #include "Service_Libs/load_balance/load_balance_api.h"
00028 #include "Service_Libs/mle_service/mle_service_api.h"
00029 #include "nsdynmemLIB.h"
00030 #include "ns_list.h"
00031 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00032 #include "mlme.h"
00033 #include "mac_api.h"
00034 #include "sw_mac.h"
00035 #include "6LoWPAN/MAC/mac_helper.h"
00036 #include "6LoWPAN/MAC/mac_data_poll.h"
00037 #include "libNET/src/net_load_balance_internal.h"
00038 #ifdef ECC
00039 #include "libX509_V3.h"
00040 #include "ecc.h"
00041 #endif
00042 #ifdef PANA
00043 #include "Security/PANA/pana.h"
00044 #include "Security/PANA/pana_internal_api.h"
00045 #endif
00046 #include "6LoWPAN/ND/nd_router_object.h"
00047 #ifdef HAVE_RPL
00048 #include "RPL/rpl_control.h"
00049 #endif
00050 
00051 #define TRACE_GROUP "6lb"
00052 
00053 static uint8_t net_load_balance_priority_get(const void *load_balance_user)
00054 {
00055     const protocol_interface_info_entry_t *cur = load_balance_user;
00056     if (!cur->rpl_domain) {
00057         return 0;
00058     }
00059     int16_t priority = protocol_6lowpan_rpl_global_priority_get();
00060     if (priority < 0) {
00061         priority = 0;
00062     } else if (priority > 255) {
00063         priority = 255;
00064     }
00065 
00066     return priority;
00067 }
00068 
00069 static void net_load_balance_beacon_tx(const void *load_balance_user)
00070 {
00071     const protocol_interface_info_entry_t *cur = load_balance_user;
00072     mlme_set_t set_req;
00073     set_req.attr = macLoadBalancingBeaconTx;
00074     set_req.attr_index = 0;
00075     set_req.value_pointer = NULL;
00076     set_req.value_size = 0;
00077     cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
00078 
00079 }
00080 
00081 static bool net_load_balance_network_switch_req(void *load_balance_user, struct mlme_pan_descriptor_s *PANDescriptor, const uint8_t *beacon_payload, uint16_t beacon_payload_length)
00082 {
00083     protocol_interface_info_entry_t *interface = load_balance_user;
00084     //Run down current interface setup and do start
00085     if (interface->if_down(interface) != 0) {
00086         return false;
00087     }
00088 #ifdef PANA
00089     pana_reset_client_session();
00090 #endif
00091     if (interface->if_up(interface) != 0) {
00092         return false;
00093     }
00094 
00095     if (!protocol_6lowpan_bootsrap_link_set(interface, PANDescriptor, beacon_payload, beacon_payload_length)) {
00096         return false;
00097     }
00098 
00099     //Start configured bootstrap
00100     return protocol_6lowpan_bootsrap_start(interface);
00101 }
00102 
00103 static void net_load_balance_link_reject(const protocol_interface_info_entry_t *cur)
00104 {
00105     uint8_t ll_all_nodes[16];
00106     memcpy(ll_all_nodes, ADDR_LINK_LOCAL_ALL_NODES, 16);
00107     mle_service_interface_receiver_handler_update(cur->id, NULL);
00108     mle_service_reject_message_build(cur->id, ll_all_nodes, false);
00109 
00110     nd_router_t *nd_router = nd_get_object_by_nwk_id(cur->nwk_id);
00111     if (nd_router) {
00112         nd_router->nd_timer = 0;
00113         nd_router->ns_forward_timer = 0;
00114         nd_router->mle_advert_timer = 0;
00115     }
00116 }
00117 
00118 static bool net_load_balance_network_switch_notify_cb(const void *load_balance_user, load_balance_nwk_switch_operation operation, uint16_t *timeout)
00119 {
00120     const protocol_interface_info_entry_t *cur = load_balance_user;
00121     switch (operation) {
00122         case LB_ROUTER_LEAVE:
00123             if (arm_nwk_6lowpan_rpl_dodag_poison(cur->id) == 0) {
00124                 *timeout = 8;
00125             } else {
00126                 *timeout = 0;
00127             }
00128             break;
00129 
00130         case LB_NEIGHBOUR_LEAVE:
00131             net_load_balance_link_reject(cur);
00132             *timeout = 4;
00133             break;
00134     }
00135     return true;
00136 }
00137 #endif
00138 
00139 int8_t net_load_balance_network_switch_cb_set(int8_t interface_id, net_load_balance_network_switch_notify *network_switch_notify)
00140 {
00141 #ifdef HAVE_6LOWPAN_ND
00142     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00143     if (!interface_ptr) {
00144         return -1;
00145     }
00146 
00147     return load_balance_network_switch_cb_set(interface_ptr->lb_api, network_switch_notify);
00148 #else
00149     return -1;
00150 #endif
00151 }
00152 
00153 
00154 int8_t net_load_balance_create(int8_t interface_id, bool  enable_periodic_beacon_interval)
00155 {
00156 #ifdef HAVE_6LOWPAN_ND
00157     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00158     if (!interface_ptr || !interface_ptr->mac_api) {
00159         return -1;
00160     } else if (interface_ptr->lb_api) {
00161         return -3;
00162     }
00163     //Allocate load balance user class
00164     load_balance_api_t *lb_api = load_balance_create(net_load_balance_network_switch_notify_cb, enable_periodic_beacon_interval);
00165     if (!lb_api) {
00166         return -2;
00167     }
00168     //Here initialize load balance based on current mac max beacon data size
00169     uint16_t beacon_payload_size;
00170     if (interface_ptr->mac_api->phyMTU > MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) {
00171         beacon_payload_size = MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE - MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD;
00172     } else {
00173         beacon_payload_size = interface_ptr->mac_api->phyMTU - MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD;
00174     }
00175 
00176     if (lb_api->lb_initialize(lb_api, net_load_balance_beacon_tx, net_load_balance_priority_get, net_load_balance_network_switch_req, beacon_payload_size, interface_ptr) != 0) {
00177         load_balance_delete(lb_api);
00178         return -2;
00179     }
00180 
00181     //Store here load balance class pointer pointer
00182     interface_ptr->lb_api = lb_api;
00183 
00184     //Enable if
00185     if ((interface_ptr->lowpan_info & (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) == (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) {
00186         net_load_balance_internal_state_activate(interface_ptr, true);
00187     }
00188 
00189     return 0;
00190 #else
00191     return -1;
00192 #endif
00193 }
00194 
00195 
00196 int8_t net_load_balance_delete(int8_t interface_id)
00197 {
00198 #ifdef HAVE_6LOWPAN_ND
00199     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00200     if (!interface_ptr) {
00201         return -1;
00202     }
00203     load_balance_api_t *lb_api = interface_ptr->lb_api;
00204     interface_ptr->lb_api = NULL;
00205 
00206     return load_balance_delete(lb_api);
00207 #else
00208     return -1;
00209 #endif
00210 }
00211 
00212 int8_t net_load_balance_threshold_set(int8_t interface_id, uint8_t threshold_min, uint8_t threshold_max)
00213 {
00214 #ifdef HAVE_6LOWPAN_ND
00215     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00216     if (!interface_ptr) {
00217         return -1;
00218     }
00219 
00220     if (threshold_min > threshold_max) {
00221         return -1;
00222     }
00223 
00224     return load_balance_network_threshold_set(interface_ptr->lb_api, threshold_min, threshold_max);
00225 #else
00226     return -1;
00227 #endif
00228 }
00229 
00230 void net_load_balance_internal_state_activate(protocol_interface_info_entry_t *interface_ptr, bool state)
00231 {
00232 #ifdef HAVE_6LOWPAN_ND
00233     if (!interface_ptr || !interface_ptr->lb_api || !interface_ptr->mac_api) {
00234         return;
00235     }
00236     uint32_t trigle_period = 3600;
00237     uint32_t route_lifetime_period = 3600;
00238     //Enable Load Balance
00239 #ifdef HAVE_RPL
00240     if (state && interface_ptr->rpl_domain) {
00241         struct rpl_instance *instance = rpl_control_lookup_instance(interface_ptr->rpl_domain, 1, NULL);
00242         if (instance) {
00243             const rpl_dodag_conf_t *dodag_config = rpl_control_get_dodag_config(instance);
00244             if (dodag_config) {
00245                 //dio max Period caluclate in seconds
00246                 uint32_t Imax_ms = (dodag_config->dio_interval_min + dodag_config->dio_interval_doublings) < 32 ?
00247                                    (1ul << (dodag_config->dio_interval_min + dodag_config->dio_interval_doublings)) : 0xfffffffful;
00248                 trigle_period = Imax_ms / 1000;
00249                 route_lifetime_period = (uint32_t)dodag_config->default_lifetime * dodag_config->lifetime_unit;
00250 
00251             }
00252         }
00253     }
00254 #endif
00255     interface_ptr->lb_api->lb_enable(interface_ptr->lb_api, state, trigle_period, route_lifetime_period);
00256     mlme_set_t set_req;
00257     set_req.attr = macLoadBalancingAcceptAnyBeacon;
00258     set_req.attr_index = 0;
00259     set_req.value_pointer = &state;
00260     set_req.value_size = sizeof(bool);
00261     interface_ptr->mac_api->mlme_req(interface_ptr->mac_api, MLME_SET, &set_req);
00262 #endif
00263 
00264 }
00265 
00266 #ifdef HAVE_RPL
00267 #ifdef HAVE_6LOWPAN_BORDER_ROUTER
00268 static int8_t net_load_balance_api_get_node_count_cb(void *lb_user, uint16_t *node_count)
00269 {
00270     protocol_interface_info_entry_t *interface_ptr = lb_user;
00271     if (rpl_control_get_instance_dao_target_count(interface_ptr->rpl_domain, 1, NULL, NULL, node_count)) {
00272         return 0;
00273     }
00274 
00275     return -1;
00276 }
00277 #endif
00278 #endif
00279 
00280 #ifdef HAVE_RPL
00281 #ifdef HAVE_6LOWPAN_BORDER_ROUTER
00282 static int8_t net_load_balance_api_get_set_load_level_cb(void *lb_user, uint8_t load_level)
00283 {
00284     //Call DODAG preference
00285     protocol_interface_info_entry_t *interface_ptr = lb_user;
00286     if (!interface_ptr->rpl_domain || interface_ptr->rpl_domain != protocol_6lowpan_rpl_domain || !protocol_6lowpan_rpl_root_dodag) {
00287         return -1;
00288     }
00289 
00290     if (load_level > RPL_DODAG_PREF_MASK) {
00291         load_level = RPL_DODAG_PREF_MASK;
00292     }
00293 
00294     rpl_control_set_dodag_pref(protocol_6lowpan_rpl_root_dodag, RPL_DODAG_PREF_MASK - load_level);
00295     return 0;
00296 }
00297 #endif
00298 #endif
00299 
00300 int8_t net_load_balance_load_level_update_enable(int8_t interface_id, uint16_t expected_device_count)
00301 {
00302 #ifdef HAVE_RPL
00303 #ifdef HAVE_6LOWPAN_BORDER_ROUTER
00304     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00305     if (!interface_ptr) {
00306         return -1;
00307     }
00308 
00309     uint16_t temp16 = expected_device_count % 8;
00310     if (temp16) {
00311         expected_device_count += (8 - temp16);
00312     }
00313 
00314     return load_balance_network_load_monitor_enable(interface_ptr->lb_api, expected_device_count, RPL_DODAG_PREF_MASK + 1, net_load_balance_api_get_node_count_cb, net_load_balance_api_get_set_load_level_cb);
00315 #else
00316     (void)interface_id;
00317     (void)expected_device_count;
00318     return -1;
00319 #endif
00320 #else
00321     (void)interface_id;
00322     (void)expected_device_count;
00323     return -1;
00324 #endif
00325 }
00326 
00327 /**
00328  * \brief Disable automatic network load level update
00329  *
00330  * \param interface_id interface id
00331  *
00332  * \return 0 process ok -1 Unknown interface id
00333  */
00334 int8_t net_load_balance_load_level_update_disable(int8_t interface_id)
00335 {
00336 #ifdef HAVE_RPL
00337 #ifdef HAVE_6LOWPAN_BORDER_ROUTER
00338     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00339     if (!interface_ptr) {
00340         return -1;
00341     }
00342 
00343     return load_balance_network_load_monitor_disable(interface_ptr->lb_api);
00344 #else
00345     (void)interface_id;
00346     return -1;
00347 #endif
00348 #else
00349     (void)interface_id;
00350     return -1;
00351 #endif
00352 }
00353 
00354 int8_t net_load_balance_set_max_probability(int8_t interface_id, uint8_t max_p)
00355 {
00356 #ifdef HAVE_6LOWPAN_ND
00357     protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
00358     if (!interface_ptr) {
00359         return -1;
00360     }
00361 
00362     return load_balance_set_max_probability(interface_ptr->lb_api, max_p);
00363 #else
00364     return -1;
00365 #endif
00366 }