Skip to content

Commit 9ff35ab

Browse files
author
Juha Heiskanen
committed
ETX calculate and sampling update.
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
1 parent 535c005 commit 9ff35ab

File tree

8 files changed

+291
-26
lines changed

8 files changed

+291
-26
lines changed

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,10 +669,6 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
669669
if (etx == 0) {
670670
return 0xffff;
671671
}
672-
if (etx > 0x800) {
673-
// 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.
674-
etx = 0x800;
675-
}
676672

677673
//tr_debug("ws_etx_read etx:%d", etx);
678674
return etx;
@@ -1466,6 +1462,13 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
14661462
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
14671463
return -1;
14681464
}
1465+
if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT)) {
1466+
etx_storage_list_allocate(cur->id, 0);
1467+
return -1;
1468+
}
1469+
1470+
etx_max_update_set(WS_ETX_MAX_UPDATE);
1471+
14691472
if (blacklist_init() != 0) {
14701473
tr_err("MLE blacklist init failed.");
14711474
return -1;

source/6LoWPAN/ws/ws_common_defines.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ typedef struct ws_bs_ie {
198198

199199
#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100
200200

201+
#define WS_ETX_MIN_SAMPLE_COUNT 4
202+
203+
#define WS_ETX_MAX_UPDATE 1024
204+
205+
#define WS_ETX_MIN_WAIT_TIME 60
206+
201207
/**
202208
* Wi-sun spesific non-preferred prefix policy label
203209
*/

source/NWK_INTERFACE/protocol_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
8282
#include "Service_Libs/load_balance/load_balance_api.h"
8383
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
84+
#include "Service_Libs/etx/etx.h"
8485

8586
#include "mac_api.h"
8687
#include "ethernet_mac_api.h"
@@ -260,6 +261,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
260261
if (cur->nwk_wpan_nvm_api) {
261262
cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, false);
262263
}
264+
etx_cache_timer(cur->id, seconds);
263265
}
264266
} else if (cur->nwk_id == IF_IPV6) {
265267
//Slow Pointer Update

source/Service_Libs/etx/etx.c

Lines changed: 220 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "Core/include/ns_address_internal.h"
2727
#include "MLE/mle.h"
28+
#include "NWK_INTERFACE/Include/protocol_abstract.h"
2829
#include "NWK_INTERFACE/Include/protocol.h"
2930
#include "NWK_INTERFACE/Include/protocol_stats.h"
3031
#include "Service_Libs/etx/etx.h"
@@ -40,14 +41,21 @@ static uint16_t etx_current_calc(uint16_t etx, uint8_t accumulated_failures);
4041
static uint16_t etx_dbm_lqi_calc(uint8_t lqi, int8_t dbm);
4142
static void etx_value_change_callback_needed_check(uint16_t etx, uint16_t *stored_diff_etx, uint8_t accumulated_failures, uint8_t attribute_index);
4243
static void etx_accum_failures_callback_needed_check(etx_storage_t *entry, uint8_t attribute_index);
44+
static void etx_cache_entry_init(uint8_t attribute_index);
45+
4346

4447
typedef struct {
45-
uint16_t hysteresis; // 12 bit fraction
46-
uint8_t accum_threshold;
4748
etx_value_change_handler_t *callback_ptr;
4849
etx_accum_failures_handler_t *accum_cb_ptr;
4950
etx_storage_t *etx_storage_list;
51+
etx_sample_storage_t *etx_cache_storage_list;
52+
uint32_t max_etx_update;
53+
uint16_t hysteresis; // 12 bit fraction
54+
uint8_t accum_threshold;
55+
uint8_t etx_min_sampling_time;
5056
uint8_t ext_storage_list_size;
57+
uint8_t min_sample_count;
58+
bool cache_sample_requested;
5159
int8_t interface_id;
5260
} ext_info_t;
5361

@@ -57,10 +65,107 @@ static ext_info_t etx_info = {
5765
.callback_ptr = NULL,
5866
.accum_cb_ptr = NULL,
5967
.etx_storage_list = NULL,
68+
.etx_cache_storage_list = NULL,
6069
.ext_storage_list_size = 0,
70+
.min_sample_count = 0,
71+
.max_etx_update = 0,
72+
.cache_sample_requested = false,
73+
.etx_min_sampling_time = 0,
6174
.interface_id = -1
6275
};
6376

77+
static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t acks_rx, uint8_t attribute_index)
78+
{
79+
if (etx_info.hysteresis && !entry->stored_diff_etx) {
80+
entry->stored_diff_etx = entry->etx;
81+
}
82+
83+
84+
uint32_t etx = attempts << (12 - ETX_MOVING_AVERAGE_FRACTION);
85+
86+
if (acks_rx > 1) {
87+
etx /= acks_rx;
88+
}
89+
90+
if ((etx_info.max_etx_update) && etx > etx_info.max_etx_update) {
91+
etx = etx_info.max_etx_update;
92+
}
93+
94+
//Add old etx 7/8 to new one
95+
etx += entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);
96+
97+
if (etx > 0xffff) {
98+
etx = 0xffff;
99+
}
100+
101+
// If real ETX value has been received do not update based on LQI or dBm
102+
entry->tmp_etx = false;
103+
entry->etx = etx;
104+
105+
etx_cache_entry_init(attribute_index);
106+
107+
// Checks if ETX value change callback is needed
108+
etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index);
109+
}
110+
111+
static void etx_cache_entry_init(uint8_t attribute_index)
112+
{
113+
if (!etx_info.cache_sample_requested) {
114+
return;
115+
}
116+
117+
etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index;
118+
storage->attempts_count = 0;
119+
storage->etx_timer = etx_info.etx_min_sampling_time;
120+
storage->received_acks = 0;
121+
storage->sample_count = 0;
122+
}
123+
124+
static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *entry, uint8_t time)
125+
{
126+
if (storage->etx_timer && time) {
127+
if (time >= storage->etx_timer) {
128+
storage->etx_timer = 0;
129+
} else {
130+
storage->etx_timer -= time;
131+
}
132+
}
133+
134+
if (entry->etx_samples == 7) {
135+
//Slower ETX update phase
136+
if (storage->sample_count < etx_info.min_sample_count || storage->etx_timer) {
137+
if (storage->sample_count < 0xff) {
138+
return false;
139+
}
140+
}
141+
} else {
142+
//Accelerated ETX at for new neighbor
143+
if (storage->sample_count < 3) {
144+
return false;
145+
}
146+
}
147+
148+
tr_debug("ETX update possible %u attempts, %u rx ack", storage->attempts_count, storage->received_acks);
149+
150+
return true;
151+
152+
}
153+
154+
155+
static etx_sample_storage_t *etx_cache_sample_update(uint8_t attribute_index, uint8_t attempts, bool ack_rx)
156+
{
157+
etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index;
158+
storage->attempts_count += attempts;
159+
if (ack_rx) {
160+
storage->received_acks++;
161+
}
162+
storage->sample_count++;
163+
return storage;
164+
165+
}
166+
167+
168+
64169
/**
65170
* \brief A function to update ETX value based on transmission attempts
66171
*
@@ -74,7 +179,6 @@ static ext_info_t etx_info = {
74179
*/
75180
void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool success, uint8_t attribute_index)
76181
{
77-
uint32_t etx;
78182
uint8_t accumulated_failures;
79183
// Gets table entry
80184
etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index);
@@ -85,6 +189,18 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
85189
entry->etx_samples++;
86190
}
87191

192+
if (etx_info.cache_sample_requested && !entry->tmp_etx) {
193+
194+
etx_sample_storage_t *storage = etx_cache_sample_update(attribute_index, attempts, success);
195+
entry->accumulated_failures = 0;
196+
if (!etx_update_possible(storage, entry, 0)) {
197+
return;
198+
}
199+
200+
etx_calculation(entry, storage->attempts_count, storage->received_acks, attribute_index);
201+
return;
202+
}
203+
88204
accumulated_failures = entry->accumulated_failures;
89205

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

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

112224
if (success) {
113-
// ETX = 7/8 * current ETX + 1/8 * ((attempts + failed attempts) << 12)
114-
etx = entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);
115-
etx += (attempts + accumulated_failures) << (12 - ETX_MOVING_AVERAGE_FRACTION);
116-
117-
if (etx > 0xffff) {
118-
entry->etx = 0xffff;
119-
} else {
120-
entry->etx = etx;
121-
}
225+
etx_calculation(entry, attempts + accumulated_failures, 1, attribute_index);
122226
}
123-
124-
// If real ETX value has been received do not update based on LQI or dBm
125-
entry->tmp_etx = false;
126-
127-
// Checks if ETX value change callback is needed
128-
etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index);
129227
}
130228
}
131229

@@ -437,6 +535,9 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
437535
{
438536
if (!etx_storage_size) {
439537
ns_dyn_mem_free(etx_info.etx_storage_list);
538+
ns_dyn_mem_free(etx_info.etx_cache_storage_list);
539+
etx_info.etx_cache_storage_list = NULL;
540+
etx_info.cache_sample_requested = false;
440541
etx_info.etx_storage_list = NULL;
441542
etx_info.ext_storage_list_size = 0;
442543
return true;
@@ -447,12 +548,18 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
447548
}
448549

449550
ns_dyn_mem_free(etx_info.etx_storage_list);
551+
etx_info.cache_sample_requested = false;
450552
etx_info.ext_storage_list_size = 0;
451553
etx_info.etx_storage_list = ns_dyn_mem_alloc(sizeof(etx_storage_t) * etx_storage_size);
554+
452555
if (!etx_info.etx_storage_list) {
556+
ns_dyn_mem_free(etx_info.etx_storage_list);
557+
etx_info.etx_storage_list = NULL;
558+
etx_info.ext_storage_list_size = 0;
453559
return false;
454560
}
455561

562+
456563
etx_info.ext_storage_list_size = etx_storage_size;
457564
etx_info.interface_id = interface_id;
458565
etx_storage_t *list_ptr = etx_info.etx_storage_list;
@@ -465,6 +572,52 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
465572

466573
}
467574

575+
bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count)
576+
{
577+
//No ini ETX allocation done yet
578+
if (etx_info.ext_storage_list_size == 0) {
579+
return false;
580+
}
581+
582+
if (min_wait_time || etx_min_sample_count) {
583+
if (!etx_info.etx_cache_storage_list) {
584+
//allocate
585+
etx_info.etx_cache_storage_list = ns_dyn_mem_alloc(sizeof(etx_sample_storage_t) * etx_info.ext_storage_list_size);
586+
587+
if (!etx_info.etx_cache_storage_list) {
588+
return false;
589+
}
590+
etx_info.cache_sample_requested = true;
591+
etx_sample_storage_t *sample_list = etx_info.etx_cache_storage_list;
592+
for (uint8_t i = 0; i < etx_info.ext_storage_list_size; i++) {
593+
memset(sample_list, 0, sizeof(etx_sample_storage_t));
594+
sample_list++;
595+
}
596+
}
597+
598+
} else {
599+
//Free Cache table we not need that anymore
600+
etx_info.cache_sample_requested = false;
601+
ns_dyn_mem_free(etx_info.etx_cache_storage_list);
602+
etx_info.etx_cache_storage_list = NULL;
603+
}
604+
605+
etx_info.min_sample_count = etx_min_sample_count;
606+
etx_info.etx_min_sampling_time = min_wait_time;
607+
tr_debug("ETX cached parameter's %u MinSample, %u MinTime", etx_info.min_sample_count, etx_info.etx_min_sampling_time);
608+
609+
return true;
610+
}
611+
612+
void etx_max_update_set(uint16_t etx_max_update)
613+
{
614+
if (etx_max_update) {
615+
etx_info.max_etx_update = (etx_max_update / 128) << (12 - ETX_MOVING_AVERAGE_FRACTION);
616+
} else {
617+
etx_info.max_etx_update = 0;
618+
}
619+
}
620+
468621
etx_storage_t *etx_storage_entry_get(int8_t interface_id, uint8_t attribute_index)
469622
{
470623
if (etx_info.interface_id != interface_id || !etx_info.etx_storage_list || attribute_index >= etx_info.ext_storage_list_size) {
@@ -593,6 +746,12 @@ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index)
593746
}
594747
etx_info.callback_ptr(etx_info.interface_id, stored_diff_etx, 0xffff, attribute_index);
595748
}
749+
750+
if (etx_info.cache_sample_requested) {
751+
//Clear cached values
752+
etx_sample_storage_t *cache_entry = etx_info.etx_cache_storage_list + attribute_index;
753+
memset(cache_entry, 0, sizeof(etx_sample_storage_t));
754+
}
596755
//Clear all data base back to zero for new user
597756
memset(entry, 0, sizeof(etx_storage_t));
598757
}
@@ -626,3 +785,42 @@ void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index)
626785
}
627786
}
628787
}
788+
789+
void etx_cache_timer(int8_t interface_id, uint16_t seconds_update)
790+
{
791+
if (!etx_info.cache_sample_requested) {
792+
return;
793+
}
794+
795+
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
796+
if (!interface) {
797+
return;
798+
}
799+
800+
mac_neighbor_table_t *table_class = mac_neighbor_info(interface);
801+
if (!table_class) {
802+
return;
803+
}
804+
805+
uint8_t update_seconds;
806+
if (seconds_update > 255) {
807+
update_seconds = 255;
808+
} else {
809+
update_seconds = seconds_update;
810+
}
811+
812+
ns_list_foreach(mac_neighbor_table_entry_t, neighbour, &table_class->neighbour_list) {
813+
814+
etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, neighbour->index);
815+
816+
if (!etx_entry || etx_entry->tmp_etx) {
817+
continue;
818+
}
819+
etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + neighbour->index;
820+
821+
if (etx_update_possible(storage, etx_entry, update_seconds)) {
822+
etx_calculation(etx_entry, storage->attempts_count, storage->received_acks, neighbour->index);
823+
}
824+
}
825+
826+
}

0 commit comments

Comments
 (0)