Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,594 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "eventOS_scheduler.h"
|
||||
#include "eventOS_callback_timer.h"
|
||||
#include "load_balance_api.h"
|
||||
#include "string.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "randLIB.h"
|
||||
#include "mlme.h"
|
||||
|
||||
typedef enum {
|
||||
LB_NWK_SWITCH_IDLE = 0,
|
||||
LB_NWK_SWITCH_ROUTER_LEAVE,
|
||||
LB_NWK_SWITCH_NEIGHBOUR_LEAVE
|
||||
} lb_nwk_switch_state_t;
|
||||
|
||||
typedef enum {
|
||||
LB_IDLE_STATE = 0,
|
||||
LB_BLOCK_STATE,
|
||||
LB_ACCEPT_STATE,
|
||||
LB_BLOCK_COMPARE,
|
||||
LB_BLOCK_NETWORK_SELECT,
|
||||
} lb_state_t;
|
||||
|
||||
/**
|
||||
* @brief struct lb_network_s Load balance network information
|
||||
*
|
||||
*/
|
||||
typedef struct lb_network_s {
|
||||
struct mlme_pan_descriptor_s PANDescriptor;
|
||||
uint8_t priority;
|
||||
bool network_switch_accepted;
|
||||
lb_nwk_switch_state_t state;
|
||||
uint16_t state_timer;
|
||||
uint16_t beacon_data_length;
|
||||
uint8_t beacon_data[];
|
||||
} lb_network_t;
|
||||
|
||||
/** get pointer to Mac header start point*/
|
||||
#define beacon_payload_start_pointer(x) (&(x)->beacon_data[0])
|
||||
|
||||
typedef struct lb_monitor_internal_s {
|
||||
load_balance_api_get_node_count *get_count_cb;
|
||||
load_balance_api_set_load_level *set_new_load_cb;
|
||||
uint16_t expected_node_count;
|
||||
uint8_t network_load_scaler;
|
||||
uint8_t last_load_level;
|
||||
uint16_t timer2update;
|
||||
} lb_monitor_internal_t;
|
||||
|
||||
|
||||
typedef struct lb_internal_s {
|
||||
load_balance_api_t *lb_api;
|
||||
lb_monitor_internal_t *lb_border_router;
|
||||
//user spesific callback
|
||||
load_balance_beacon_tx *load_balance_beacon_tx_cb;
|
||||
load_balance_priority_get *lb_priority_get_cb;
|
||||
load_balance_network_switch_req *lb_nwk_switch_cb;
|
||||
load_balance_network_switch_notify *lb_nwk_switch_notify; //Can be NULL if app not want to control
|
||||
//APP defined nwk switch callback
|
||||
net_load_balance_network_switch_notify *lb_access_switch_cb;
|
||||
void *lb_user_parent_id;
|
||||
lb_network_t *notified_network;
|
||||
uint32_t triggle_period;
|
||||
uint32_t lb_state_timer;
|
||||
uint32_t time_to_next_beacon;
|
||||
uint16_t beacon_max_payload_length;
|
||||
uint8_t nwk_switch_threshold_min;
|
||||
uint8_t nwk_switch_threshold_max;
|
||||
uint8_t nwk_maX_P;
|
||||
lb_state_t lb_state;
|
||||
bool load_balance_activate;
|
||||
bool periodic_beacon_activated;
|
||||
} lb_internal_t;
|
||||
|
||||
|
||||
/**
|
||||
* Load balance internal variables
|
||||
*/
|
||||
static load_balance_api_t lb_api;
|
||||
static lb_internal_t *lb_store = NULL;
|
||||
|
||||
/**
|
||||
* Load balance internal used functions
|
||||
*/
|
||||
static lb_internal_t *load_balance_class_allocate(void);
|
||||
static void load_balance_class_free(lb_internal_t *api);
|
||||
static lb_internal_t *lb_api_get(const load_balance_api_t *api);
|
||||
static bool load_balance_network_class_allocate(lb_internal_t *lb_store_ptr, uint16_t beacon_max_payload_length);
|
||||
static void lb_network_switch_handle(lb_internal_t *this);
|
||||
static void lb_load_level_poll(lb_internal_t *this, uint32_t trigle_period);
|
||||
|
||||
/**
|
||||
* Load balance shared functions to user
|
||||
*/
|
||||
static void lb_beacon_notify(const load_balance_api_t *api, const struct mlme_beacon_ind_s *beacon_ind, uint8_t priority);
|
||||
static void lb_enable(const load_balance_api_t *api, bool active_state, uint32_t network_triggle_max_period, uint32_t network_route_life_time);
|
||||
static int8_t lb_api_initialize(load_balance_api_t *api, load_balance_beacon_tx *lb_beacon_tx,
|
||||
load_balance_priority_get *priority_get_cb, load_balance_network_switch_req *lb_nwk_switch_cb, uint16_t baecon_max_payload_length, void *lb_user);
|
||||
static void lb_second_ticks(const load_balance_api_t *api);
|
||||
|
||||
#define TRACE_GROUP "lba"
|
||||
|
||||
/**
|
||||
* Load balance border router class allocate
|
||||
*/
|
||||
static lb_monitor_internal_t *lb_border_router_api_allocate(lb_internal_t *api)
|
||||
{
|
||||
if (!api->lb_border_router) {
|
||||
api->lb_border_router = ns_dyn_mem_alloc(sizeof(lb_monitor_internal_t));
|
||||
}
|
||||
return api->lb_border_router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load balance border router class free
|
||||
*/
|
||||
static int8_t lb_border_router_api_free(lb_internal_t *api)
|
||||
{
|
||||
if (api->lb_border_router) {
|
||||
ns_dyn_mem_free(api->lb_border_router);
|
||||
api->lb_border_router = NULL;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate Load balance class base
|
||||
*/
|
||||
static lb_internal_t *load_balance_class_allocate(void)
|
||||
{
|
||||
if (lb_store) {
|
||||
if (lb_store->lb_user_parent_id) {
|
||||
return NULL;
|
||||
}
|
||||
return lb_store;
|
||||
}
|
||||
|
||||
lb_internal_t *store = ns_dyn_mem_alloc(sizeof(lb_internal_t));
|
||||
if (store) {
|
||||
|
||||
store->lb_api = &lb_api;
|
||||
lb_api.lb_beacon_notify = lb_beacon_notify;
|
||||
lb_api.lb_enable = lb_enable;
|
||||
lb_api.lb_initialize = lb_api_initialize;
|
||||
lb_api.lb_seconds_tick_update = lb_second_ticks;
|
||||
|
||||
store->lb_border_router = NULL;
|
||||
store->load_balance_beacon_tx_cb = NULL;
|
||||
store->lb_nwk_switch_cb = NULL;
|
||||
store->lb_priority_get_cb = NULL;
|
||||
store->lb_user_parent_id = NULL;
|
||||
store->notified_network = NULL;
|
||||
store->lb_access_switch_cb = NULL;
|
||||
store->beacon_max_payload_length = 0;
|
||||
store->nwk_switch_threshold_max = 0;
|
||||
store->nwk_switch_threshold_min = 0;
|
||||
store->nwk_maX_P = 25;
|
||||
store->load_balance_activate = false;
|
||||
store->time_to_next_beacon = 0;
|
||||
store->triggle_period = 0;
|
||||
lb_store = store;
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free allocated load balance class
|
||||
*/
|
||||
static void load_balance_class_free(lb_internal_t *api)
|
||||
{
|
||||
//Clean heared networks
|
||||
ns_dyn_mem_free(api->notified_network);
|
||||
lb_border_router_api_free(api);
|
||||
ns_dyn_mem_free(api);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load balance class get by user API pointer
|
||||
*/
|
||||
static lb_internal_t *lb_api_get(const load_balance_api_t *api)
|
||||
{
|
||||
if (!api || !lb_store || lb_store->lb_api != api) {
|
||||
return NULL;
|
||||
}
|
||||
return lb_store;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allocate notified network class
|
||||
*/
|
||||
static bool load_balance_network_class_allocate(lb_internal_t *lb_store_ptr, uint16_t beacon_max_payload_length)
|
||||
{
|
||||
ns_dyn_mem_free(lb_store_ptr->notified_network);
|
||||
lb_store_ptr->beacon_max_payload_length = 0;
|
||||
if (beacon_max_payload_length) {
|
||||
lb_store_ptr->notified_network = ns_dyn_mem_alloc(sizeof(lb_network_t) + beacon_max_payload_length);
|
||||
if (!lb_store_ptr->notified_network) {
|
||||
return false;
|
||||
}
|
||||
lb_store_ptr->notified_network->network_switch_accepted = false;
|
||||
lb_store_ptr->notified_network->priority = 0xff;
|
||||
lb_store_ptr->notified_network->state = LB_NWK_SWITCH_IDLE;
|
||||
lb_store_ptr->notified_network->state_timer = 0;
|
||||
lb_store_ptr->beacon_max_payload_length = beacon_max_payload_length;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to notified and selected network
|
||||
*/
|
||||
static void lb_network_switch_handle(lb_internal_t *this)
|
||||
{
|
||||
lb_network_t *network_class = this->notified_network;
|
||||
if (network_class->state_timer) {
|
||||
network_class->state_timer--;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (network_class->state) {
|
||||
case LB_NWK_SWITCH_IDLE:
|
||||
if (!this->notified_network->network_switch_accepted) {
|
||||
if (this->lb_access_switch_cb && !this->lb_access_switch_cb()) {
|
||||
return;
|
||||
}
|
||||
this->notified_network->network_switch_accepted = true;
|
||||
}
|
||||
tr_info("Start NWK switch statemachine!");
|
||||
this->lb_nwk_switch_notify(this->lb_user_parent_id, LB_ROUTER_LEAVE, &network_class->state_timer);
|
||||
network_class->state = LB_NWK_SWITCH_ROUTER_LEAVE;
|
||||
break;
|
||||
|
||||
case LB_NWK_SWITCH_ROUTER_LEAVE:
|
||||
tr_info("Router leave state!");
|
||||
this->lb_nwk_switch_notify(this->lb_user_parent_id, LB_NEIGHBOUR_LEAVE, &network_class->state_timer);
|
||||
network_class->state = LB_NWK_SWITCH_NEIGHBOUR_LEAVE;
|
||||
break;
|
||||
|
||||
case LB_NWK_SWITCH_NEIGHBOUR_LEAVE:
|
||||
tr_info("Neighbour leave state!");
|
||||
//Disable beacon send
|
||||
lb_enable(this->lb_api, false, 0, 0);
|
||||
this->lb_nwk_switch_cb(this->lb_user_parent_id, &network_class->PANDescriptor, beacon_payload_start_pointer(network_class), network_class->beacon_data_length);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool lb_accept_beacon_state(lb_state_t lb_state)
|
||||
{
|
||||
//Check state
|
||||
switch (lb_state) {
|
||||
case LB_IDLE_STATE:
|
||||
case LB_BLOCK_STATE:
|
||||
case LB_BLOCK_COMPARE:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Beacon notify handler
|
||||
*/
|
||||
static void lb_beacon_notify(const load_balance_api_t *api, const struct mlme_beacon_ind_s *beacon_ind, uint8_t priority)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!beacon_ind || !this || !this->nwk_switch_threshold_max || !this->nwk_switch_threshold_min) {
|
||||
return;
|
||||
} else if (!lb_accept_beacon_state(this->lb_state)) {
|
||||
return;
|
||||
} else if (beacon_ind->beacon_data_length > this->beacon_max_payload_length) {
|
||||
return;
|
||||
}
|
||||
|
||||
lb_network_t *nwk = this->notified_network;
|
||||
//Get current global part joining priority
|
||||
uint8_t current_priority = this->lb_priority_get_cb(this->lb_user_parent_id);
|
||||
|
||||
if (this->lb_state == LB_ACCEPT_STATE) {
|
||||
//Compare new network priority
|
||||
if (current_priority < priority) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t diff = current_priority - priority;
|
||||
uint16_t switch_prob; // 256 * percent (0-25600)
|
||||
|
||||
if (diff >= this->nwk_switch_threshold_max) {
|
||||
switch_prob = this->nwk_maX_P * 256;
|
||||
tr_debug("diff %"PRIu16", tmax %"PRIu8" %"PRIu16, diff, this->nwk_switch_threshold_max, switch_prob);
|
||||
} else if (diff <= this->nwk_switch_threshold_min) {
|
||||
tr_debug("diff %"PRIu16", tmin %"PRIu8, diff, this->nwk_switch_threshold_min);
|
||||
switch_prob = 0;
|
||||
} else {
|
||||
// The multiplication could overflow 16-bit, even though the final result will be 16-bit
|
||||
switch_prob = (uint32_t) this->nwk_maX_P * 256 * (diff - this->nwk_switch_threshold_min) / (this->nwk_switch_threshold_max - this->nwk_switch_threshold_min);
|
||||
tr_debug("diff between min & max, diff %"PRIu16", tmax %"PRIu8" prob%"PRIu16, diff, this->nwk_switch_threshold_max, switch_prob);
|
||||
}
|
||||
|
||||
if (switch_prob > randLIB_get_random_in_range(0, 25599)) {
|
||||
this->lb_state_timer = randLIB_get_random_in_range(1, 32);
|
||||
this->lb_state = LB_BLOCK_NETWORK_SELECT;
|
||||
} else {
|
||||
//Enter Block state
|
||||
this->lb_state_timer = this->triggle_period;
|
||||
this->lb_state = LB_BLOCK_COMPARE;
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
//Compare priority to saved network
|
||||
if (priority > nwk->priority) {
|
||||
return;
|
||||
} else if (priority == nwk->priority && nwk->PANDescriptor.LinkQuality > beacon_ind->PANDescriptor.LinkQuality) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Copy network info
|
||||
nwk->priority = priority;
|
||||
nwk->PANDescriptor = beacon_ind->PANDescriptor;
|
||||
memcpy(beacon_payload_start_pointer(nwk), beacon_ind->beacon_data, beacon_ind->beacon_data_length);
|
||||
nwk->beacon_data_length = beacon_ind->beacon_data_length;
|
||||
}
|
||||
/**
|
||||
* Load balance activate or disable
|
||||
*/
|
||||
static void lb_enable(const load_balance_api_t *api, bool active_state, uint32_t network_triggle_max_period, uint32_t network_route_life_time)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this || !this->lb_user_parent_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->load_balance_activate = active_state;
|
||||
|
||||
if (active_state) {
|
||||
//Start Block_period
|
||||
this->triggle_period = network_triggle_max_period;
|
||||
this->lb_state = LB_BLOCK_STATE;
|
||||
tr_debug("Enable Network Triggle max time %"PRIu32" %"PRIu32" route life time", network_triggle_max_period, network_route_life_time);
|
||||
if (this->nwk_switch_threshold_min && this->nwk_switch_threshold_max) {
|
||||
this->lb_state_timer = network_route_life_time > network_triggle_max_period ? network_route_life_time : network_triggle_max_period;
|
||||
} else {
|
||||
this->lb_state_timer = 10;
|
||||
if (this->lb_border_router) {
|
||||
this->lb_border_router->timer2update = 0;
|
||||
lb_load_level_poll(this, this->triggle_period);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
this->lb_state = LB_IDLE_STATE;
|
||||
}
|
||||
|
||||
if (this->notified_network) {
|
||||
this->notified_network->priority = 0xff;
|
||||
this->notified_network->network_switch_accepted = false;
|
||||
this->notified_network->state = LB_NWK_SWITCH_IDLE;
|
||||
this->notified_network->state_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load balance activate or disable
|
||||
*/
|
||||
static int8_t lb_api_initialize(load_balance_api_t *api, load_balance_beacon_tx *lb_beacon_tx,
|
||||
load_balance_priority_get *priority_get_cb, load_balance_network_switch_req *lb_nwk_switch_cb, uint16_t beacon_max_payload_length, void *lb_user)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this || !lb_beacon_tx || !priority_get_cb || !lb_nwk_switch_cb || !lb_user) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Allocate beacon payload here
|
||||
if (!load_balance_network_class_allocate(this, beacon_max_payload_length)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
this->lb_user_parent_id = lb_user;
|
||||
this->load_balance_beacon_tx_cb = lb_beacon_tx;
|
||||
this->lb_nwk_switch_cb = lb_nwk_switch_cb;
|
||||
this->lb_priority_get_cb = priority_get_cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lb_load_level_poll(lb_internal_t *this, uint32_t trigle_period)
|
||||
{
|
||||
if (!this->lb_border_router || !this->lb_user_parent_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->lb_border_router->timer2update) {
|
||||
this->lb_border_router->timer2update--;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t node_count;
|
||||
if (this->lb_border_router->get_count_cb(this->lb_user_parent_id, &node_count) != 0) {
|
||||
this->lb_border_router->last_load_level = 0xff;
|
||||
this->lb_border_router->timer2update = 10;
|
||||
return;
|
||||
}
|
||||
//Calculate
|
||||
uint8_t new_load;
|
||||
if (node_count >= this->lb_border_router->expected_node_count) {
|
||||
new_load = this->lb_border_router->network_load_scaler - 1;
|
||||
} else {
|
||||
uint16_t scaled_level = this->lb_border_router->expected_node_count / this->lb_border_router->network_load_scaler;
|
||||
new_load = node_count / scaled_level;
|
||||
}
|
||||
|
||||
if (this->lb_border_router->last_load_level != new_load) {
|
||||
|
||||
if (this->lb_border_router->set_new_load_cb(this->lb_user_parent_id, new_load) == 0) {
|
||||
this->lb_border_router->last_load_level = new_load;
|
||||
}
|
||||
}
|
||||
this->lb_border_router->timer2update = trigle_period >> 1; //Update Every block period / 2
|
||||
}
|
||||
|
||||
static void lb_second_ticks(const load_balance_api_t *api)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this || this->lb_state == LB_IDLE_STATE) {
|
||||
return;
|
||||
}
|
||||
|
||||
lb_load_level_poll(this, this->triggle_period);
|
||||
|
||||
//Update Next beacon generation timer
|
||||
if (this->periodic_beacon_activated && this->lb_state != LB_BLOCK_STATE && --this->time_to_next_beacon == 0) {
|
||||
this->time_to_next_beacon = this->triggle_period;
|
||||
this->load_balance_beacon_tx_cb(this->lb_user_parent_id);
|
||||
}
|
||||
|
||||
if (this->lb_state_timer == 0) {
|
||||
|
||||
switch (this->lb_state) {
|
||||
case LB_BLOCK_STATE:
|
||||
//Enter block state to accept state
|
||||
this->lb_state = LB_ACCEPT_STATE;
|
||||
this->time_to_next_beacon = randLIB_get_random_in_range(1, 32);
|
||||
break;
|
||||
case LB_BLOCK_COMPARE:
|
||||
this->lb_state = LB_ACCEPT_STATE;
|
||||
break;
|
||||
case LB_BLOCK_NETWORK_SELECT:
|
||||
lb_network_switch_handle(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this->lb_state_timer--;
|
||||
}
|
||||
}
|
||||
|
||||
load_balance_api_t *load_balance_create(load_balance_network_switch_notify *lb_notify_cb, bool activate_periodic_beacon)
|
||||
{
|
||||
//validate beacon period & beacon_notify
|
||||
if (!lb_notify_cb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//allocate load balance class
|
||||
lb_internal_t *this = load_balance_class_allocate();
|
||||
if (!this) {
|
||||
return NULL;
|
||||
}
|
||||
this->lb_state = LB_IDLE_STATE;
|
||||
this->lb_nwk_switch_notify = lb_notify_cb;
|
||||
this->periodic_beacon_activated = activate_periodic_beacon;
|
||||
|
||||
return this->lb_api;
|
||||
}
|
||||
|
||||
int load_balance_delete(load_balance_api_t *api)
|
||||
{
|
||||
if (!lb_store || lb_store->lb_api != api) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
load_balance_class_free(lb_store);
|
||||
lb_store = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_balance_network_threshold_set(load_balance_api_t *api, uint8_t threshold_min, uint8_t threshold_max)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->nwk_switch_threshold_min = threshold_min;
|
||||
this->nwk_switch_threshold_max = threshold_max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_balance_network_load_monitor_enable(load_balance_api_t *api, uint16_t expected_node_count, uint8_t network_load_scaler, load_balance_api_get_node_count *get_count_cb, load_balance_api_set_load_level *set_new_load_cb)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
if (expected_node_count == 0 || network_load_scaler == 0 || expected_node_count < network_load_scaler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!get_count_cb || !set_new_load_cb) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lb_monitor_internal_t *border_router = lb_border_router_api_allocate(this);
|
||||
if (!border_router) {
|
||||
return -2;
|
||||
}
|
||||
border_router->expected_node_count = expected_node_count;
|
||||
border_router->network_load_scaler = network_load_scaler;
|
||||
border_router->get_count_cb = get_count_cb;
|
||||
border_router->last_load_level = 0xff;
|
||||
border_router->set_new_load_cb = set_new_load_cb;
|
||||
border_router->timer2update = 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_balance_network_load_monitor_disable(load_balance_api_t *api)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
return lb_border_router_api_free(this);
|
||||
}
|
||||
|
||||
int load_balance_set_max_probability(load_balance_api_t *api, uint8_t max_p)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
if (max_p > 100 || max_p == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->nwk_maX_P = max_p;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int load_balance_network_switch_cb_set(load_balance_api_t *api, net_load_balance_network_switch_notify *network_switch_notify)
|
||||
{
|
||||
lb_internal_t *this = lb_api_get(api);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->lb_access_switch_cb = network_switch_notify;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file load_balance_api.h
|
||||
* \brief A API class to support 6lowpan network load balance which based on RPL routing.
|
||||
*/
|
||||
|
||||
#ifndef LOAD_BALANCE_API_H
|
||||
#define LOAD_BALANCE_API_H
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "net_load_balance_api.h"
|
||||
|
||||
typedef struct load_balance_api load_balance_api_t;
|
||||
|
||||
struct mlme_beacon_ind_s;
|
||||
struct mlme_pan_descriptor_s;
|
||||
|
||||
typedef enum {
|
||||
LB_ROUTER_LEAVE,
|
||||
LB_NEIGHBOUR_LEAVE
|
||||
} load_balance_nwk_switch_operation;
|
||||
|
||||
/**
|
||||
* Application which want enable load balance must first create load balance class, e.g 'load_balance_api_t* load_balance_create()'
|
||||
* In the function external Nanostack needs to fill necessary function pointers so that Upper layer can use it.
|
||||
* For load balance user define:
|
||||
* - load_balance_beacon_notify: Beacon notify should call this api
|
||||
* - load_balance_api_initialize: Initialise load balance class with next function pointer
|
||||
* - load_balance_enable
|
||||
* Load Balance requested function pointers
|
||||
* - load_balance_priority_get
|
||||
* - load_balance_network_switch_req
|
||||
* - load_balance_beacon_interval_set
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief load_balance_beacon_notify
|
||||
* \param api load_balance_api_t pointer
|
||||
* \param beacon_ind standard beacon indication structure
|
||||
* \param priority Beacon parsed network priority
|
||||
*/
|
||||
typedef void load_balance_beacon_notify(const load_balance_api_t *api, const struct mlme_beacon_ind_s *beacon_ind, uint8_t priority);
|
||||
|
||||
/**
|
||||
* \brief load_balance_second_ticks update load balance state timer
|
||||
* \param load_balance_api_t pointer
|
||||
*/
|
||||
typedef void load_balance_second_ticks(const load_balance_api_t *api);
|
||||
|
||||
/**
|
||||
* \brief load_balance_enabled handler for enabled or disable beacon notify
|
||||
* \param load_balance_api_t pointer
|
||||
* \param active_state true enable load balancer and false disable
|
||||
* \param network_triggle_max_period time that load balance will send periodic beacon
|
||||
* \param network_route_life_time time for device route lifetime
|
||||
*/
|
||||
typedef void load_balance_enable(const load_balance_api_t *api,
|
||||
bool active_state, uint32_t network_triggle_max_period,
|
||||
uint32_t network_route_life_time);
|
||||
|
||||
/**
|
||||
* \brief load_balance_priority_get function for load balance to get current advertisement priority
|
||||
* \param load_balance_user pointer to load balancer user initialised data
|
||||
*
|
||||
* \return priority
|
||||
*/
|
||||
typedef uint8_t load_balance_priority_get(const void *load_balance_user);
|
||||
|
||||
/**
|
||||
* \brief load_balance_beacon_tx function for trig periodically beacon
|
||||
* \param load_balance_user pointer to load balancer user initialised data
|
||||
*
|
||||
*/
|
||||
typedef void load_balance_beacon_tx(const void *load_balance_user);
|
||||
|
||||
/**
|
||||
* \brief load_balance_network_switch_notify this function will be called by load balance when it have detected better network to switch change state
|
||||
* \param load_balance_user pointer to load balancer user initialised data
|
||||
* \param operation network switch operation
|
||||
* \param timeout pointer where operation time must be define NULL when load balance not need time out or user set 0
|
||||
*
|
||||
* \return true Network switching can be performed immediately
|
||||
* \return false Network switching will be performed later
|
||||
*/
|
||||
typedef bool load_balance_network_switch_notify(const void *load_balance_user, load_balance_nwk_switch_operation operation, uint16_t *timeout);
|
||||
|
||||
/**
|
||||
* \brief load_balance_network_switch_req this function will be called by load balance when it have detected better network to switch
|
||||
* \param load_balance_user pointer to load balancer user initialised data
|
||||
* \param PANDescriptor pointer to link and coordinator info
|
||||
* \param beacon_payload beacon payload pointer for new network
|
||||
* \param beacon_payload_length payload length
|
||||
*
|
||||
* \return true network switch started
|
||||
* \return false network switch fail
|
||||
*/
|
||||
typedef bool 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);
|
||||
|
||||
|
||||
/**
|
||||
* \brief load_balance_api_get_node_count Get border router registered node count
|
||||
* \param lb_user Load balancing user defined unique data.
|
||||
* \param node_count Pointer where node count is stored
|
||||
* \return -1 Get fail, 0 node_count include current node count
|
||||
*/
|
||||
typedef int8_t load_balance_api_get_node_count(void *lb_user, uint16_t *node_count);
|
||||
|
||||
/**
|
||||
* \brief load_balance_api_set_load_level Update new load level to network
|
||||
* \param lb_user Load balancing user defined unique data.
|
||||
* \param load_level load level which could be [0,CONFIGURED_SCALER -1]
|
||||
* \return -1 Set fail, 0 New Network Load is updated
|
||||
*/
|
||||
typedef int8_t load_balance_api_set_load_level(void *lb_user, uint8_t load_level);
|
||||
|
||||
/**
|
||||
* \brief load_balance_api_initialize Initialises load balancer needed callback.
|
||||
* \param api load_balance_api_t pointer, which is created by application.
|
||||
* \param lb_beacon_tx_period_set_cb Upper layer function to handle MCPS confirmations
|
||||
* \param priority_get_cb Upper layer function to handle MCPS indications
|
||||
* \param lb_nwk_switch_cb
|
||||
* \param beacon_max_payload_length Set 0 if network switch is disabled otherwise give max supported beacon payload.
|
||||
* \param lb_user Load balancing user defined unique data
|
||||
* \return -1 if error, -2 if Out of Memory, 0 otherwise
|
||||
*/
|
||||
typedef int8_t load_balance_api_initialize(load_balance_api_t *api, load_balance_beacon_tx *lb_beacon_tx,
|
||||
load_balance_priority_get *priority_get_cb, load_balance_network_switch_req *lb_nwk_switch_cb, uint16_t beacon_max_payload_length, void *lb_user);
|
||||
|
||||
/**
|
||||
* \brief Struct load_balance_api_s defines functions for two-way communications between load balance and user.
|
||||
* Nanostack creates load_balance_api_s object by calling load_balance_create() function.
|
||||
* Then object is passed to Upper layer which then initialises it's own callback functions.
|
||||
*/
|
||||
struct load_balance_api {
|
||||
load_balance_api_initialize *lb_initialize;
|
||||
load_balance_enable *lb_enable;
|
||||
load_balance_beacon_notify *lb_beacon_notify;
|
||||
load_balance_second_ticks *lb_seconds_tick_update;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Create load balance class
|
||||
* \param lb_notify_cb user callback for accept network switch
|
||||
* \param activate_periodic_beacon True define that load balance will generate periodic beacon based configured value at enable
|
||||
*
|
||||
* \return Pointer to load balance class
|
||||
*/
|
||||
load_balance_api_t *load_balance_create(load_balance_network_switch_notify *lb_notify_cb, bool activate_periodic_beacon);
|
||||
|
||||
/**
|
||||
* \brief Delete load balance class and free memory
|
||||
* \param api Class pointer to deleted class
|
||||
*
|
||||
* \return 0 process ok -1 Unknown class
|
||||
*/
|
||||
int load_balance_delete(load_balance_api_t *api);
|
||||
|
||||
/**
|
||||
* \brief Set load balance threshold min and max
|
||||
*
|
||||
* Nework switch will work next diff_priority >= randLIB_get_random_in_range(threshold_min, threshold_max) --> switch network if true
|
||||
* For border router Disable Network compare set threshold_min and threshold_max to 0.
|
||||
*
|
||||
* \param api Class pointer to deleted class
|
||||
* \param threshold_min minimal threshold value for network switch
|
||||
* \param threshold_max max threshold value for network switch
|
||||
*
|
||||
* \return 0 process ok -1 Unknown class or unsupported threshold
|
||||
*/
|
||||
int load_balance_network_threshold_set(load_balance_api_t *api, uint8_t threshold_min, uint8_t threshold_max);
|
||||
|
||||
/**
|
||||
* \brief Enable load balance load monitor and update feature
|
||||
*
|
||||
* This feature is for border router's defined function for give network scale and load parameter what load balancer will follow automatically.
|
||||
*
|
||||
* \param api Class pointer to deleted class
|
||||
* \param expected_node_count node which define max load to network
|
||||
* \param network_load_scaler Define max load value
|
||||
* \param get_count_cb function pointer for read current node count
|
||||
* \param set_new_load_cb function pointer what is called when load level must be update
|
||||
*
|
||||
* \return 0 process ok -1 Unknown class or unsupported parameter
|
||||
*/
|
||||
int load_balance_network_load_monitor_enable(load_balance_api_t *api, uint16_t expected_node_count, uint8_t network_load_scaler, load_balance_api_get_node_count *get_count_cb, load_balance_api_set_load_level *set_new_load_cb);
|
||||
|
||||
/**
|
||||
* \brief Disable load balance load monitor and update feature
|
||||
*
|
||||
* \param api Class pointer to deleted class
|
||||
*
|
||||
* \return 0 process ok -1 Unknown class
|
||||
*/
|
||||
int load_balance_network_load_monitor_disable(load_balance_api_t *api);
|
||||
|
||||
/**
|
||||
* \brief Set network probability percent when new network is better than threshold max
|
||||
*
|
||||
* \param api Class pointer to deleted class
|
||||
* \param max_p is percent probability to switch network. Default is 25%. Accepted values are [1,100] recommend values are 10-25.
|
||||
*
|
||||
* \return 0 process ok -1 Unknown class or unsupported parameter
|
||||
*/
|
||||
int load_balance_set_max_probability(load_balance_api_t *api, uint8_t max_p);
|
||||
|
||||
/**
|
||||
* \brief Set user callback for accepting the network switch.
|
||||
* \param api Class pointer to deleted class.
|
||||
* \param network_switch_notify User callback.
|
||||
*
|
||||
* \return 0 Set OK.
|
||||
* \return -1 unknown Interface.
|
||||
*/
|
||||
int load_balance_network_switch_cb_set(load_balance_api_t *api, net_load_balance_network_switch_notify *network_switch_notify);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LOAD_BALANCE_API_H
|
||||
Reference in New Issue
Block a user