46#include "net/routing/rpl-classic/rpl.h"
47#include "net/routing/rpl-classic/rpl-private.h"
48#include "net/nbr-table.h"
49#include "net/link-stats.h"
53#define LOG_MODULE "RPL"
54#define LOG_LEVEL LOG_LEVEL_RPL
75#ifdef RPL_MRHOF_CONF_SQUARED_ETX
76#define RPL_MRHOF_SQUARED_ETX RPL_MRHOF_CONF_SQUARED_ETX
78#define RPL_MRHOF_SQUARED_ETX 0
81#if !RPL_MRHOF_SQUARED_ETX
84#define MAX_LINK_METRIC 1024
92#define PARENT_SWITCH_THRESHOLD 96
94#define MAX_LINK_METRIC 2048
95#define PARENT_SWITCH_THRESHOLD 160
100#define MAX_PATH_COST 32768
106 LOG_INFO(
"Reset MRHOF\n");
111dao_ack_callback(rpl_parent_t *p,
int status)
113 if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) {
117 LOG_DBG(
"MRHOF - DAO ACK received with status: %d\n", status);
118 if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
120 link_stats_packet_sent(rpl_get_parent_lladdr(p),
MAC_TX_OK, 10);
121 }
else if(status == RPL_DAO_ACK_TIMEOUT) {
123 link_stats_packet_sent(rpl_get_parent_lladdr(p),
MAC_TX_OK, 10);
129parent_link_metric(rpl_parent_t *p)
131 const struct link_stats *stats = rpl_get_parent_link_stats(p);
133#if RPL_MRHOF_SQUARED_ETX
134 uint32_t squared_etx = ((uint32_t)stats->etx * stats->etx) / LINK_STATS_ETX_DIVISOR;
135 return (uint16_t)MIN(squared_etx, 0xffff);
144parent_path_cost(rpl_parent_t *p)
148 if(p == NULL || p->dag == NULL || p->dag->instance == NULL) {
154 switch(p->dag->instance->mc.type) {
156 base = p->mc.obj.etx;
158 case RPL_DAG_MC_ENERGY:
159 base = p->mc.obj.energy.energy_est << 8;
170 return MIN((uint32_t)base + parent_link_metric(p), 0xffff);
174rank_via_parent(rpl_parent_t *p)
176 uint16_t min_hoprankinc;
179 if(p == NULL || p->dag == NULL || p->dag->instance == NULL) {
180 return RPL_INFINITE_RANK;
183 min_hoprankinc = p->dag->instance->min_hoprankinc;
184 path_cost = parent_path_cost(p);
187 return MAX(MIN((uint32_t)p->rank + min_hoprankinc, 0xffff), path_cost);
191parent_is_acceptable(rpl_parent_t *p)
193 uint16_t link_metric = parent_link_metric(p);
194 uint16_t path_cost = parent_path_cost(p);
196 return link_metric <= MAX_LINK_METRIC && path_cost <= MAX_PATH_COST;
200parent_has_usable_link(rpl_parent_t *p)
202 uint16_t link_metric = parent_link_metric(p);
204 return link_metric <= MAX_LINK_METRIC;
208best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
213 int p1_is_acceptable;
214 int p2_is_acceptable;
216 p1_is_acceptable = p1 != NULL && parent_is_acceptable(p1);
217 p2_is_acceptable = p2 != NULL && parent_is_acceptable(p2);
219 if(!p1_is_acceptable) {
220 return p2_is_acceptable ? p2 : NULL;
222 if(!p2_is_acceptable) {
223 return p1_is_acceptable ? p1 : NULL;
227 p1_cost = parent_path_cost(p1);
228 p2_cost = parent_path_cost(p2);
231 if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
232 if(p1_cost < p2_cost + PARENT_SWITCH_THRESHOLD &&
233 p1_cost > p2_cost - PARENT_SWITCH_THRESHOLD) {
234 return dag->preferred_parent;
238 return p1_cost < p2_cost ? p1 : p2;
244 if(d1->grounded != d2->grounded) {
245 return d1->grounded ? d1 : d2;
248 if(d1->preference != d2->preference) {
249 return d1->preference > d2->preference ? d1 : d2;
252 return d1->rank < d2->rank ? d1 : d2;
259 instance->mc.type = RPL_DAG_MC_NONE;
269 dag = instance->current_dag;
270 if(dag == NULL || !dag->joined) {
271 LOG_WARN(
"Cannot update the metric container when not joined\n");
275 if(dag->rank == ROOT_RANK(instance)) {
278 instance->mc.type = RPL_DAG_MC;
279 instance->mc.flags = 0;
280 instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
281 instance->mc.prec = 0;
282 path_cost = dag->rank;
284 path_cost = parent_path_cost(dag->preferred_parent);
288 switch(instance->mc.type) {
289 case RPL_DAG_MC_NONE:
292 instance->mc.length =
sizeof(instance->mc.obj.etx);
293 instance->mc.obj.etx = path_cost;
295 case RPL_DAG_MC_ENERGY:
296 instance->mc.length =
sizeof(instance->mc.obj.energy);
297 if(dag->rank == ROOT_RANK(instance)) {
298 type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
300 type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
302 instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
305 instance->mc.obj.energy.energy_est = path_cost >> 8;
308 LOG_WARN(
"MRHOF, non-supported MC %u\n", instance->mc.type);
320 parent_has_usable_link,
325 update_metric_container,
Header file for the logging system.
@ MAC_TX_OK
The MAC layer transmission was OK.
API for RPL objective functions (OF)