49 #include "net/rpl/rpl-private.h"
50 #include "net/nbr-table.h"
52 #define DEBUG DEBUG_NONE
55 static void reset(rpl_dag_t *);
56 static void neighbor_link_callback(rpl_parent_t *,
int,
int);
57 static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
58 static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *);
59 static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
60 static void update_metric_container(rpl_instance_t *);
62 rpl_of_t rpl_mrhof = {
64 neighbor_link_callback,
68 update_metric_container,
77 #define MAX_LINK_METRIC 10
80 #define MAX_PATH_COST 100
86 #define PARENT_SWITCH_THRESHOLD_DIV 2
88 typedef uint16_t rpl_path_metric_t;
90 static rpl_path_metric_t
91 calculate_path_metric(rpl_parent_t *p)
94 return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
97 #if RPL_DAG_MC == RPL_DAG_MC_NONE
98 return p->rank + (uint16_t)p->link_metric;
99 #elif RPL_DAG_MC == RPL_DAG_MC_ETX
100 return p->mc.obj.etx + (uint16_t)p->link_metric;
101 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
102 return p->mc.obj.energy.energy_est + (uint16_t)p->link_metric;
104 #error
"Unsupported RPL_DAG_MC configured. See rpl.h."
109 reset(rpl_dag_t *dag)
111 PRINTF(
"RPL: Reset MRHOF\n");
115 neighbor_link_callback(rpl_parent_t *p,
int status,
int numtx)
117 uint16_t recorded_etx = p->link_metric;
118 uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR;
124 packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
127 if(p->flags & RPL_PARENT_FLAG_LINK_METRIC_VALID) {
129 new_etx = ((uint32_t)recorded_etx * ETX_ALPHA +
130 (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
133 new_etx = packet_etx;
135 p->flags |= RPL_PARENT_FLAG_LINK_METRIC_VALID;
138 PRINTF(
"RPL: ETX changed from %u to %u (packet ETX = %u)\n",
139 (
unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR),
140 (
unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR),
141 (
unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR));
142 p->link_metric = new_etx;
147 calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
150 rpl_rank_t rank_increase;
154 return INFINITE_RANK;
156 rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
158 rank_increase = p->link_metric;
164 if(INFINITE_RANK - base_rank < rank_increase) {
166 new_rank = INFINITE_RANK;
170 new_rank = base_rank + rank_increase;
177 best_dag(rpl_dag_t *d1, rpl_dag_t *d2)
179 if(d1->grounded != d2->grounded) {
180 return d1->grounded ? d1 : d2;
183 if(d1->preference != d2->preference) {
184 return d1->preference > d2->preference ? d1 : d2;
187 return d1->rank < d2->rank ? d1 : d2;
190 static rpl_parent_t *
191 best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
194 rpl_path_metric_t min_diff;
195 rpl_path_metric_t p1_metric;
196 rpl_path_metric_t p2_metric;
200 min_diff = RPL_DAG_MC_ETX_DIVISOR /
201 PARENT_SWITCH_THRESHOLD_DIV;
203 p1_metric = calculate_path_metric(p1);
204 p2_metric = calculate_path_metric(p2);
207 if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
208 if(p1_metric < p2_metric + min_diff &&
209 p1_metric > p2_metric - min_diff) {
210 PRINTF(
"RPL: MRHOF hysteresis: %u <= %u <= %u\n",
211 p2_metric - min_diff,
213 p2_metric + min_diff);
214 return dag->preferred_parent;
218 return p1_metric < p2_metric ? p1 : p2;
221 #if RPL_DAG_MC == RPL_DAG_MC_NONE
223 update_metric_container(rpl_instance_t *instance)
225 instance->mc.type = RPL_DAG_MC;
229 update_metric_container(rpl_instance_t *instance)
231 rpl_path_metric_t path_metric;
233 #if RPL_DAG_MC == RPL_DAG_MC_ENERGY
237 instance->mc.type = RPL_DAG_MC;
238 instance->mc.flags = RPL_DAG_MC_FLAG_P;
239 instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
240 instance->mc.prec = 0;
242 dag = instance->current_dag;
245 PRINTF(
"RPL: Cannot update the metric container when not joined\n");
249 if(dag->rank == ROOT_RANK(instance)) {
252 path_metric = calculate_path_metric(dag->preferred_parent);
255 #if RPL_DAG_MC == RPL_DAG_MC_ETX
256 instance->mc.length =
sizeof(instance->mc.obj.etx);
257 instance->mc.obj.etx = path_metric;
259 PRINTF(
"RPL: My path ETX to the root is %u.%u\n",
260 instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
261 (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) /
262 RPL_DAG_MC_ETX_DIVISOR);
263 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
264 instance->mc.length =
sizeof(instance->mc.obj.energy);
266 if(dag->rank == ROOT_RANK(instance)) {
267 type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
269 type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
272 instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
273 instance->mc.obj.energy.energy_est = path_metric;
The MAC layer deferred the transmission for a later time.
#define NULL
The null pointer.
The MAC layer transmission was OK.
A set of debugging macros.