Skip to content

Commit

Permalink
ETX calculate and sampling update.
Browse files Browse the repository at this point in the history
Added possibility for sampling configured count of etx sample in min spesific time for genertae new ETX.

Wi-SUN bootsrap ETX read hack removed.

Wi-sun enable new cached mode with 4 sample and 60 seconds period.

Change-Id: I8de28e484d6a6885fb492a5d6a349a31926837f5
  • Loading branch information
Juha Heiskanen committed May 2, 2019
1 parent 535c005 commit 9ff35ab
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 26 deletions.
11 changes: 7 additions & 4 deletions source/6LoWPAN/ws/ws_bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,6 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
if (etx == 0) {
return 0xffff;
}
if (etx > 0x800) {
// Wi-SUN section 6.2.3.1.6.1 says ETX can only be maximum of 1024 (8*128) in RPL units, ie 8.0.
etx = 0x800;
}

//tr_debug("ws_etx_read etx:%d", etx);
return etx;
Expand Down Expand Up @@ -1466,6 +1462,13 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
return -1;
}
if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT)) {
etx_storage_list_allocate(cur->id, 0);
return -1;
}

etx_max_update_set(WS_ETX_MAX_UPDATE);

if (blacklist_init() != 0) {
tr_err("MLE blacklist init failed.");
return -1;
Expand Down
6 changes: 6 additions & 0 deletions source/6LoWPAN/ws/ws_common_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ typedef struct ws_bs_ie {

#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100

#define WS_ETX_MIN_SAMPLE_COUNT 4

#define WS_ETX_MAX_UPDATE 1024

#define WS_ETX_MIN_WAIT_TIME 60

/**
* Wi-sun spesific non-preferred prefix policy label
*/
Expand Down
2 changes: 2 additions & 0 deletions source/NWK_INTERFACE/protocol_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "Service_Libs/load_balance/load_balance_api.h"
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
#include "Service_Libs/etx/etx.h"

#include "mac_api.h"
#include "ethernet_mac_api.h"
Expand Down Expand Up @@ -260,6 +261,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
if (cur->nwk_wpan_nvm_api) {
cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, false);
}
etx_cache_timer(cur->id, seconds);
}
} else if (cur->nwk_id == IF_IPV6) {
//Slow Pointer Update
Expand Down
242 changes: 220 additions & 22 deletions source/Service_Libs/etx/etx.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "Core/include/ns_address_internal.h"
#include "MLE/mle.h"
#include "NWK_INTERFACE/Include/protocol_abstract.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "Service_Libs/etx/etx.h"
Expand All @@ -40,14 +41,21 @@ static uint16_t etx_current_calc(uint16_t etx, uint8_t accumulated_failures);
static uint16_t etx_dbm_lqi_calc(uint8_t lqi, int8_t dbm);
static void etx_value_change_callback_needed_check(uint16_t etx, uint16_t *stored_diff_etx, uint8_t accumulated_failures, uint8_t attribute_index);
static void etx_accum_failures_callback_needed_check(etx_storage_t *entry, uint8_t attribute_index);
static void etx_cache_entry_init(uint8_t attribute_index);


typedef struct {
uint16_t hysteresis; // 12 bit fraction
uint8_t accum_threshold;
etx_value_change_handler_t *callback_ptr;
etx_accum_failures_handler_t *accum_cb_ptr;
etx_storage_t *etx_storage_list;
etx_sample_storage_t *etx_cache_storage_list;
uint32_t max_etx_update;
uint16_t hysteresis; // 12 bit fraction
uint8_t accum_threshold;
uint8_t etx_min_sampling_time;
uint8_t ext_storage_list_size;
uint8_t min_sample_count;
bool cache_sample_requested;
int8_t interface_id;
} ext_info_t;

Expand All @@ -57,10 +65,107 @@ static ext_info_t etx_info = {
.callback_ptr = NULL,
.accum_cb_ptr = NULL,
.etx_storage_list = NULL,
.etx_cache_storage_list = NULL,
.ext_storage_list_size = 0,
.min_sample_count = 0,
.max_etx_update = 0,
.cache_sample_requested = false,
.etx_min_sampling_time = 0,
.interface_id = -1
};

static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t acks_rx, uint8_t attribute_index)
{
if (etx_info.hysteresis && !entry->stored_diff_etx) {
entry->stored_diff_etx = entry->etx;
}


uint32_t etx = attempts << (12 - ETX_MOVING_AVERAGE_FRACTION);

if (acks_rx > 1) {
etx /= acks_rx;
}

if ((etx_info.max_etx_update) && etx > etx_info.max_etx_update) {
etx = etx_info.max_etx_update;
}

//Add old etx 7/8 to new one
etx += entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);

if (etx > 0xffff) {
etx = 0xffff;
}

// If real ETX value has been received do not update based on LQI or dBm
entry->tmp_etx = false;
entry->etx = etx;

etx_cache_entry_init(attribute_index);

// Checks if ETX value change callback is needed
etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index);
}

static void etx_cache_entry_init(uint8_t attribute_index)
{
if (!etx_info.cache_sample_requested) {
return;
}

etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index;
storage->attempts_count = 0;
storage->etx_timer = etx_info.etx_min_sampling_time;
storage->received_acks = 0;
storage->sample_count = 0;
}

static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *entry, uint8_t time)
{
if (storage->etx_timer && time) {
if (time >= storage->etx_timer) {
storage->etx_timer = 0;
} else {
storage->etx_timer -= time;
}
}

if (entry->etx_samples == 7) {
//Slower ETX update phase
if (storage->sample_count < etx_info.min_sample_count || storage->etx_timer) {
if (storage->sample_count < 0xff) {
return false;
}
}
} else {
//Accelerated ETX at for new neighbor
if (storage->sample_count < 3) {
return false;
}
}

tr_debug("ETX update possible %u attempts, %u rx ack", storage->attempts_count, storage->received_acks);

return true;

}


static etx_sample_storage_t *etx_cache_sample_update(uint8_t attribute_index, uint8_t attempts, bool ack_rx)
{
etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index;
storage->attempts_count += attempts;
if (ack_rx) {
storage->received_acks++;
}
storage->sample_count++;
return storage;

}



/**
* \brief A function to update ETX value based on transmission attempts
*
Expand All @@ -74,7 +179,6 @@ static ext_info_t etx_info = {
*/
void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool success, uint8_t attribute_index)
{
uint32_t etx;
uint8_t accumulated_failures;
// Gets table entry
etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index);
Expand All @@ -85,6 +189,18 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
entry->etx_samples++;
}

if (etx_info.cache_sample_requested && !entry->tmp_etx) {

etx_sample_storage_t *storage = etx_cache_sample_update(attribute_index, attempts, success);
entry->accumulated_failures = 0;
if (!etx_update_possible(storage, entry, 0)) {
return;
}

etx_calculation(entry, storage->attempts_count, storage->received_acks, attribute_index);
return;
}

accumulated_failures = entry->accumulated_failures;

if (!success) {
Expand All @@ -104,28 +220,10 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
}

if (entry->etx) {
// If hysteresis is set stores ETX value for comparison
if (etx_info.hysteresis && !entry->stored_diff_etx) {
entry->stored_diff_etx = entry->etx;
}

if (success) {
// ETX = 7/8 * current ETX + 1/8 * ((attempts + failed attempts) << 12)
etx = entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);
etx += (attempts + accumulated_failures) << (12 - ETX_MOVING_AVERAGE_FRACTION);

if (etx > 0xffff) {
entry->etx = 0xffff;
} else {
entry->etx = etx;
}
etx_calculation(entry, attempts + accumulated_failures, 1, attribute_index);
}

// If real ETX value has been received do not update based on LQI or dBm
entry->tmp_etx = false;

// Checks if ETX value change callback is needed
etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index);
}
}

Expand Down Expand Up @@ -437,6 +535,9 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
{
if (!etx_storage_size) {
ns_dyn_mem_free(etx_info.etx_storage_list);
ns_dyn_mem_free(etx_info.etx_cache_storage_list);
etx_info.etx_cache_storage_list = NULL;
etx_info.cache_sample_requested = false;
etx_info.etx_storage_list = NULL;
etx_info.ext_storage_list_size = 0;
return true;
Expand All @@ -447,12 +548,18 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
}

ns_dyn_mem_free(etx_info.etx_storage_list);
etx_info.cache_sample_requested = false;
etx_info.ext_storage_list_size = 0;
etx_info.etx_storage_list = ns_dyn_mem_alloc(sizeof(etx_storage_t) * etx_storage_size);

if (!etx_info.etx_storage_list) {
ns_dyn_mem_free(etx_info.etx_storage_list);
etx_info.etx_storage_list = NULL;
etx_info.ext_storage_list_size = 0;
return false;
}


etx_info.ext_storage_list_size = etx_storage_size;
etx_info.interface_id = interface_id;
etx_storage_t *list_ptr = etx_info.etx_storage_list;
Expand All @@ -465,6 +572,52 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)

}

bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count)
{
//No ini ETX allocation done yet
if (etx_info.ext_storage_list_size == 0) {
return false;
}

if (min_wait_time || etx_min_sample_count) {
if (!etx_info.etx_cache_storage_list) {
//allocate
etx_info.etx_cache_storage_list = ns_dyn_mem_alloc(sizeof(etx_sample_storage_t) * etx_info.ext_storage_list_size);

if (!etx_info.etx_cache_storage_list) {
return false;
}
etx_info.cache_sample_requested = true;
etx_sample_storage_t *sample_list = etx_info.etx_cache_storage_list;
for (uint8_t i = 0; i < etx_info.ext_storage_list_size; i++) {
memset(sample_list, 0, sizeof(etx_sample_storage_t));
sample_list++;
}
}

} else {
//Free Cache table we not need that anymore
etx_info.cache_sample_requested = false;
ns_dyn_mem_free(etx_info.etx_cache_storage_list);
etx_info.etx_cache_storage_list = NULL;
}

etx_info.min_sample_count = etx_min_sample_count;
etx_info.etx_min_sampling_time = min_wait_time;
tr_debug("ETX cached parameter's %u MinSample, %u MinTime", etx_info.min_sample_count, etx_info.etx_min_sampling_time);

return true;
}

void etx_max_update_set(uint16_t etx_max_update)
{
if (etx_max_update) {
etx_info.max_etx_update = (etx_max_update / 128) << (12 - ETX_MOVING_AVERAGE_FRACTION);
} else {
etx_info.max_etx_update = 0;
}
}

etx_storage_t *etx_storage_entry_get(int8_t interface_id, uint8_t attribute_index)
{
if (etx_info.interface_id != interface_id || !etx_info.etx_storage_list || attribute_index >= etx_info.ext_storage_list_size) {
Expand Down Expand Up @@ -593,6 +746,12 @@ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index)
}
etx_info.callback_ptr(etx_info.interface_id, stored_diff_etx, 0xffff, attribute_index);
}

if (etx_info.cache_sample_requested) {
//Clear cached values
etx_sample_storage_t *cache_entry = etx_info.etx_cache_storage_list + attribute_index;
memset(cache_entry, 0, sizeof(etx_sample_storage_t));
}
//Clear all data base back to zero for new user
memset(entry, 0, sizeof(etx_storage_t));
}
Expand Down Expand Up @@ -626,3 +785,42 @@ void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index)
}
}
}

void etx_cache_timer(int8_t interface_id, uint16_t seconds_update)
{
if (!etx_info.cache_sample_requested) {
return;
}

protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return;
}

mac_neighbor_table_t *table_class = mac_neighbor_info(interface);
if (!table_class) {
return;
}

uint8_t update_seconds;
if (seconds_update > 255) {
update_seconds = 255;
} else {
update_seconds = seconds_update;
}

ns_list_foreach(mac_neighbor_table_entry_t, neighbour, &table_class->neighbour_list) {

etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, neighbour->index);

if (!etx_entry || etx_entry->tmp_etx) {
continue;
}
etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + neighbour->index;

if (etx_update_possible(storage, etx_entry, update_seconds)) {
etx_calculation(etx_entry, storage->attempts_count, storage->received_acks, neighbour->index);
}
}

}
Loading

0 comments on commit 9ff35ab

Please sign in to comment.