49 #include "net/rpl/rpl.h"
50 #include "net/rpl/rpl-private.h"
51 #include "net/nbr-table.h"
52 #include "net/link-stats.h"
54 #define DEBUG DEBUG_NONE
67 #ifdef RPL_MRHOF_CONF_SQUARED_ETX
68 #define RPL_MRHOF_SQUARED_ETX RPL_MRHOF_CONF_SQUARED_ETX
70 #define RPL_MRHOF_SQUARED_ETX 0
73 #if !RPL_MRHOF_SQUARED_ETX
76 #define MAX_LINK_METRIC 1024
81 #define PARENT_SWITCH_THRESHOLD 96
83 #define MAX_LINK_METRIC 2048
84 #define PARENT_SWITCH_THRESHOLD 160
89 #define MAX_PATH_COST 32768
95 PRINTF(
"RPL: Reset MRHOF\n");
100 dao_ack_callback(rpl_parent_t *p,
int status)
102 if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) {
106 PRINTF(
"RPL: MRHOF - DAO ACK received with status: %d\n", status);
107 if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
109 link_stats_packet_sent(rpl_get_parent_lladdr(p),
MAC_TX_OK, 10);
110 }
else if(status == RPL_DAO_ACK_TIMEOUT) {
112 link_stats_packet_sent(rpl_get_parent_lladdr(p),
MAC_TX_OK, 10);
118 parent_link_metric(rpl_parent_t *p)
120 const struct link_stats *stats = rpl_get_parent_link_stats(p);
122 #if RPL_MRHOF_SQUARED_ETX
123 uint32_t squared_etx = ((uint32_t)stats->etx * stats->etx) / LINK_STATS_ETX_DIVISOR;
124 return (uint16_t)MIN(squared_etx, 0xffff);
133 parent_path_cost(rpl_parent_t *p)
137 if(p ==
NULL || p->dag ==
NULL || p->dag->instance ==
NULL) {
143 switch(p->dag->instance->mc.type) {
145 base = p->mc.obj.etx;
147 case RPL_DAG_MC_ENERGY:
148 base = p->mc.obj.energy.energy_est << 8;
159 return MIN((uint32_t)base + parent_link_metric(p), 0xffff);
163 rank_via_parent(rpl_parent_t *p)
165 uint16_t min_hoprankinc;
168 if(p ==
NULL || p->dag ==
NULL || p->dag->instance ==
NULL) {
169 return INFINITE_RANK;
172 min_hoprankinc = p->dag->instance->min_hoprankinc;
173 path_cost = parent_path_cost(p);
176 return MAX(MIN((uint32_t)p->rank + min_hoprankinc, 0xffff), path_cost);
180 parent_is_acceptable(rpl_parent_t *p)
182 uint16_t link_metric = parent_link_metric(p);
183 uint16_t path_cost = parent_path_cost(p);
185 return link_metric <= MAX_LINK_METRIC && path_cost <= MAX_PATH_COST;
189 parent_has_usable_link(rpl_parent_t *p)
191 uint16_t link_metric = parent_link_metric(p);
193 return link_metric <= MAX_LINK_METRIC;
196 static rpl_parent_t *
197 best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
202 int p1_is_acceptable;
203 int p2_is_acceptable;
205 p1_is_acceptable = p1 !=
NULL && parent_is_acceptable(p1);
206 p2_is_acceptable = p2 !=
NULL && parent_is_acceptable(p2);
208 if(!p1_is_acceptable) {
209 return p2_is_acceptable ? p2 :
NULL;
211 if(!p2_is_acceptable) {
212 return p1_is_acceptable ? p1 :
NULL;
216 p1_cost = parent_path_cost(p1);
217 p2_cost = parent_path_cost(p2);
220 if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
221 if(p1_cost < p2_cost + PARENT_SWITCH_THRESHOLD &&
222 p1_cost > p2_cost - PARENT_SWITCH_THRESHOLD) {
223 return dag->preferred_parent;
227 return p1_cost < p2_cost ? p1 : p2;
231 best_dag(rpl_dag_t *d1, rpl_dag_t *d2)
233 if(d1->grounded != d2->grounded) {
234 return d1->grounded ? d1 : d2;
237 if(d1->preference != d2->preference) {
238 return d1->preference > d2->preference ? d1 : d2;
241 return d1->rank < d2->rank ? d1 : d2;
246 update_metric_container(rpl_instance_t *instance)
248 instance->mc.type = RPL_DAG_MC_NONE;
252 update_metric_container(rpl_instance_t *instance)
258 dag = instance->current_dag;
259 if(dag ==
NULL || !dag->joined) {
260 PRINTF(
"RPL: Cannot update the metric container when not joined\n");
264 if(dag->rank == ROOT_RANK(instance)) {
266 instance->mc.type = RPL_DAG_MC;
267 instance->mc.flags = 0;
268 instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
269 instance->mc.prec = 0;
270 path_cost = dag->rank;
272 path_cost = parent_path_cost(dag->preferred_parent);
276 switch(instance->mc.type) {
277 case RPL_DAG_MC_NONE:
280 instance->mc.length =
sizeof(instance->mc.obj.etx);
281 instance->mc.obj.etx = path_cost;
283 case RPL_DAG_MC_ENERGY:
284 instance->mc.length =
sizeof(instance->mc.obj.energy);
285 if(dag->rank == ROOT_RANK(instance)) {
286 type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
288 type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
290 instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
292 instance->mc.obj.energy.energy_est = path_cost >> 8;
295 PRINTF(
"RPL: MRHOF, non-supported MC %u\n", instance->mc.type);
301 rpl_of_t rpl_mrhof = {
307 parent_has_usable_link,
312 update_metric_container,
The MAC layer transmission was OK.
#define NULL
The null pointer.
A set of debugging macros for the IP stack