25
25
26
26
#include "Core/include/ns_address_internal.h"
27
27
#include "MLE/mle.h"
28
+ #include "NWK_INTERFACE/Include/protocol_abstract.h"
28
29
#include "NWK_INTERFACE/Include/protocol.h"
29
30
#include "NWK_INTERFACE/Include/protocol_stats.h"
30
31
#include "Service_Libs/etx/etx.h"
@@ -40,14 +41,21 @@ static uint16_t etx_current_calc(uint16_t etx, uint8_t accumulated_failures);
40
41
static uint16_t etx_dbm_lqi_calc (uint8_t lqi , int8_t dbm );
41
42
static void etx_value_change_callback_needed_check (uint16_t etx , uint16_t * stored_diff_etx , uint8_t accumulated_failures , uint8_t attribute_index );
42
43
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
+
43
46
44
47
typedef struct {
45
- uint16_t hysteresis ; // 12 bit fraction
46
- uint8_t accum_threshold ;
47
48
etx_value_change_handler_t * callback_ptr ;
48
49
etx_accum_failures_handler_t * accum_cb_ptr ;
49
50
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 ;
50
56
uint8_t ext_storage_list_size ;
57
+ uint8_t min_sample_count ;
58
+ bool cache_sample_requested ;
51
59
int8_t interface_id ;
52
60
} ext_info_t ;
53
61
@@ -57,10 +65,107 @@ static ext_info_t etx_info = {
57
65
.callback_ptr = NULL ,
58
66
.accum_cb_ptr = NULL ,
59
67
.etx_storage_list = NULL ,
68
+ .etx_cache_storage_list = NULL ,
60
69
.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 ,
61
74
.interface_id = -1
62
75
};
63
76
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
+
64
169
/**
65
170
* \brief A function to update ETX value based on transmission attempts
66
171
*
@@ -74,7 +179,6 @@ static ext_info_t etx_info = {
74
179
*/
75
180
void etx_transm_attempts_update (int8_t interface_id , uint8_t attempts , bool success , uint8_t attribute_index )
76
181
{
77
- uint32_t etx ;
78
182
uint8_t accumulated_failures ;
79
183
// Gets table entry
80
184
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
85
189
entry -> etx_samples ++ ;
86
190
}
87
191
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
+
88
204
accumulated_failures = entry -> accumulated_failures ;
89
205
90
206
if (!success ) {
@@ -104,28 +220,10 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
104
220
}
105
221
106
222
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
- }
111
223
112
224
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 );
122
226
}
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 );
129
227
}
130
228
}
131
229
@@ -437,6 +535,9 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
437
535
{
438
536
if (!etx_storage_size ) {
439
537
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;
440
541
etx_info .etx_storage_list = NULL ;
441
542
etx_info .ext_storage_list_size = 0 ;
442
543
return true;
@@ -447,12 +548,18 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size)
447
548
}
448
549
449
550
ns_dyn_mem_free (etx_info .etx_storage_list );
551
+ etx_info .cache_sample_requested = false;
450
552
etx_info .ext_storage_list_size = 0 ;
451
553
etx_info .etx_storage_list = ns_dyn_mem_alloc (sizeof (etx_storage_t ) * etx_storage_size );
554
+
452
555
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 ;
453
559
return false;
454
560
}
455
561
562
+
456
563
etx_info .ext_storage_list_size = etx_storage_size ;
457
564
etx_info .interface_id = interface_id ;
458
565
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)
465
572
466
573
}
467
574
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
+
468
621
etx_storage_t * etx_storage_entry_get (int8_t interface_id , uint8_t attribute_index )
469
622
{
470
623
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)
593
746
}
594
747
etx_info .callback_ptr (etx_info .interface_id , stored_diff_etx , 0xffff , attribute_index );
595
748
}
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
+ }
596
755
//Clear all data base back to zero for new user
597
756
memset (entry , 0 , sizeof (etx_storage_t ));
598
757
}
@@ -626,3 +785,42 @@ void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index)
626
785
}
627
786
}
628
787
}
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