46 #include "net/rpl/rpl-private.h"
49 #define DEBUG DEBUG_NONE
52 static void reset(rpl_dag_t *);
53 static void parent_state_callback(rpl_parent_t *,
int,
int);
54 static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
55 static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
56 static void update_metric_container(rpl_dag_t *);
58 rpl_of_t rpl_of_etx = {
60 parent_state_callback,
63 update_metric_container,
67 #define NI_ETX_TO_RPL_ETX(etx) \
68 ((etx) * (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
69 #define RPL_ETX_TO_NI_ETX(etx) \
70 ((etx) / (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
73 #define MAX_LINK_METRIC 10
76 #define MAX_PATH_COST 100
82 #define PARENT_SWITCH_THRESHOLD_DIV 2
84 typedef uint16_t rpl_path_metric_t;
86 static rpl_path_metric_t
87 calculate_path_metric(rpl_parent_t *p)
89 if(p ==
NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag))) {
90 return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
92 return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric);
101 parent_state_callback(rpl_parent_t *parent,
int known,
int etx)
106 calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
109 rpl_rank_t rank_increase;
113 return INFINITE_RANK;
115 rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC;
117 rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc;
123 if(INFINITE_RANK - base_rank < rank_increase) {
125 new_rank = INFINITE_RANK;
129 new_rank = base_rank + rank_increase;
135 static rpl_parent_t *
136 best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
139 rpl_path_metric_t min_diff;
140 rpl_path_metric_t p1_metric;
141 rpl_path_metric_t p2_metric;
145 min_diff = RPL_DAG_MC_ETX_DIVISOR /
146 PARENT_SWITCH_THRESHOLD_DIV;
148 p1_metric = calculate_path_metric(p1);
149 p2_metric = calculate_path_metric(p2);
152 if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
153 if(p1_metric < p2_metric + min_diff &&
154 p1_metric > p2_metric - min_diff) {
155 PRINTF(
"RPL: MRHOF hysteresis: %u <= %u <= %u\n",
156 p2_metric - min_diff,
158 p2_metric + min_diff);
159 return dag->preferred_parent;
163 return p1_metric < p2_metric ? p1 : p2;
167 update_metric_container(rpl_dag_t *dag)
169 rpl_path_metric_t path_metric;
170 #if RPL_DAG_MC == RPL_DAG_MC_ENERGY
174 dag->mc.flags = RPL_DAG_MC_FLAG_P;
175 dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
178 if(dag->rank == ROOT_RANK(dag)) {
181 path_metric = calculate_path_metric(dag->preferred_parent);
184 #if RPL_DAG_MC == RPL_DAG_MC_ETX
186 dag->mc.type = RPL_DAG_MC_ETX;
187 dag->mc.length =
sizeof(dag->mc.obj.etx);
188 dag->mc.obj.etx = path_metric;
190 PRINTF(
"RPL: My path ETX to the root is %u.%u\n",
191 dag->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
192 (dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);
194 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
196 dag->mc.type = RPL_DAG_MC_ENERGY;
197 dag->mc.length =
sizeof(dag->mc.obj.energy);
199 if(dag->rank == ROOT_RANK(dag)) {
200 type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
202 type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
205 dag->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
206 dag->mc.obj.energy.energy_est = path_metric;
210 #error "Unsupported RPL_DAG_MC configured. See rpl.h."