47 #include "net/rpl/rpl-private.h"
48 #include "net/nbr-table.h"
50 #define DEBUG DEBUG_NONE
54 static void neighbor_link_callback(rpl_parent_t *,
int,
int);
55 static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
57 static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
62 neighbor_link_callback,
66 update_metric_container,
75 #define MAX_LINK_METRIC 10
78 #define MAX_PATH_COST 100
84 #define PARENT_SWITCH_THRESHOLD_DIV 2
86 typedef uint16_t rpl_path_metric_t;
88 static rpl_path_metric_t
89 calculate_path_metric(rpl_parent_t *p)
92 return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
95 #if RPL_DAG_MC == RPL_DAG_MC_NONE
96 return p->rank + (uint16_t)p->link_metric;
97 #elif RPL_DAG_MC == RPL_DAG_MC_ETX
98 return p->mc.obj.etx + (uint16_t)p->link_metric;
99 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
100 return p->mc.obj.energy.energy_est + (uint16_t)p->link_metric;
102 #error
"Unsupported RPL_DAG_MC configured. See rpl.h."
109 PRINTF(
"RPL: Reset MRHOF\n");
113 neighbor_link_callback(rpl_parent_t *p,
int status,
int numtx)
115 uint16_t recorded_etx = p->link_metric;
116 uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR;
122 packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
125 new_etx = ((uint32_t)recorded_etx * ETX_ALPHA +
126 (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
128 PRINTF(
"RPL: ETX changed from %u to %u (packet ETX = %u)\n",
129 (
unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR),
130 (
unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR),
131 (
unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR));
132 p->link_metric = new_etx;
137 calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
140 rpl_rank_t rank_increase;
144 return INFINITE_RANK;
146 rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
148 rank_increase = p->link_metric;
154 if(INFINITE_RANK - base_rank < rank_increase) {
156 new_rank = INFINITE_RANK;
160 new_rank = base_rank + rank_increase;
169 if(d1->grounded != d2->grounded) {
170 return d1->grounded ? d1 : d2;
173 if(d1->preference != d2->preference) {
174 return d1->preference > d2->preference ? d1 : d2;
177 return d1->rank < d2->rank ? d1 : d2;
180 static rpl_parent_t *
181 best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
184 rpl_path_metric_t min_diff;
185 rpl_path_metric_t p1_metric;
186 rpl_path_metric_t p2_metric;
190 min_diff = RPL_DAG_MC_ETX_DIVISOR /
191 PARENT_SWITCH_THRESHOLD_DIV;
193 p1_metric = calculate_path_metric(p1);
194 p2_metric = calculate_path_metric(p2);
197 if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
198 if(p1_metric < p2_metric + min_diff &&
199 p1_metric > p2_metric - min_diff) {
200 PRINTF(
"RPL: MRHOF hysteresis: %u <= %u <= %u\n",
201 p2_metric - min_diff,
203 p2_metric + min_diff);
204 return dag->preferred_parent;
208 return p1_metric < p2_metric ? p1 : p2;
211 #if RPL_DAG_MC == RPL_DAG_MC_NONE
215 instance->mc.type = RPL_DAG_MC;
221 rpl_path_metric_t path_metric;
223 #if RPL_DAG_MC == RPL_DAG_MC_ENERGY
227 instance->mc.type = RPL_DAG_MC;
228 instance->mc.flags = RPL_DAG_MC_FLAG_P;
229 instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
230 instance->mc.prec = 0;
232 dag = instance->current_dag;
235 PRINTF(
"RPL: Cannot update the metric container when not joined\n");
239 if(dag->rank == ROOT_RANK(instance)) {
242 path_metric = calculate_path_metric(dag->preferred_parent);
245 #if RPL_DAG_MC == RPL_DAG_MC_ETX
246 instance->mc.length =
sizeof(instance->mc.obj.etx);
247 instance->mc.obj.etx = path_metric;
249 PRINTF(
"RPL: My path ETX to the root is %u.%u\n",
250 instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
251 (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) /
252 RPL_DAG_MC_ETX_DIVISOR);
253 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
254 instance->mc.length =
sizeof(instance->mc.obj.energy);
256 if(dag->rank == ROOT_RANK(instance)) {
257 type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
259 type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
262 instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
263 instance->mc.obj.energy.energy_est = path_metric;