diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index be919fadb..1bc70dd0f 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -250,9 +250,10 @@ dio_input(void) dio.mc.aggr = buffer[i + 4] >> 4; dio.mc.prec = buffer[i + 4] & 0xf; dio.mc.length = buffer[i + 5]; + if(dio.mc.type == RPL_DAG_MC_ETX) { - dio.mc.etx.etx = buffer[i + 6] << 8; - dio.mc.etx.etx |= buffer[i + 7]; + dio.mc.obj.etx = buffer[i + 6] << 8; + dio.mc.obj.etx |= buffer[i + 7]; PRINTF("RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n", (unsigned)dio.mc.type, @@ -260,7 +261,10 @@ dio_input(void) (unsigned)dio.mc.aggr, (unsigned)dio.mc.prec, (unsigned)dio.mc.length, - (unsigned)dio.mc.etx.etx); + (unsigned)dio.mc.obj.etx); + } else if(dio.mc.type == RPL_DAG_MC_ENERGY) { + dio.mc.obj.energy.flags = buffer[i + 6]; + dio.mc.obj.energy.energy_est = buffer[i + 7]; } else { PRINTF("RPL: Unhandled DAG MC type: %u\n", (unsigned)dio.mc.type); return; @@ -380,8 +384,12 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) buffer[pos++] |= dag->mc.prec; if(dag->mc.type == RPL_DAG_MC_ETX) { buffer[pos++] = 2; - buffer[pos++] = dag->mc.etx.etx >> 8; - buffer[pos++] = dag->mc.etx.etx & 0xff; + buffer[pos++] = dag->mc.obj.etx >> 8; + buffer[pos++] = dag->mc.obj.etx & 0xff; + } else if(dag->mc.type == RPL_DAG_MC_ENERGY) { + buffer[pos++] = 2; + buffer[pos++] = dag->mc.obj.energy.flags; + buffer[pos++] = dag->mc.obj.energy.energy_est; } else { PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n", (unsigned)dag->mc.type); diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index e8ffefe1b..0b6265311 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -66,7 +66,7 @@ rpl_of_t rpl_of_etx = { #define NI_ETX_TO_RPL_ETX(etx) \ ((etx) * (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR)) -#define RPL_ETX_TO_NI_ETX(etx) \ +#define rpl_path_metric_tO_NI_ETX(etx) \ ((etx) / (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR)) /* Reject parents that have a higher link metric than the following. */ @@ -84,13 +84,12 @@ rpl_of_t rpl_of_etx = { */ #define PARENT_SWITCH_THRESHOLD_DIV 2 -typedef uint16_t rpl_etx_t; -#define MAX_ETX 65535 +typedef uint16_t rpl_path_metric_t; static uint16_t -calculate_etx(rpl_parent_t *p) +calculate_path_metric(rpl_parent_t *p) { - return p->mc.etx.etx + NI_ETX_TO_RPL_ETX(p->etx); + return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->etx); } static void @@ -140,48 +139,64 @@ static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { rpl_dag_t *dag; - rpl_etx_t min_diff; - rpl_etx_t p1_etx; - rpl_etx_t p2_etx; + rpl_path_metric_t min_diff; + rpl_path_metric_t p1_metric; + rpl_path_metric_t p2_metric; dag = p1->dag; /* Both parents must be in the same DAG. */ min_diff = RPL_DAG_MC_ETX_DIVISOR / PARENT_SWITCH_THRESHOLD_DIV; - p1_etx = calculate_etx(p1); - p2_etx = calculate_etx(p2); + p1_metric = calculate_path_metric(p1); + p2_metric = calculate_path_metric(p2); /* Maintain stability of the preferred parent in case of similar ranks. */ if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) { - if(p1_etx < p2_etx + min_diff && - p1_etx > p2_etx - min_diff) { + if(p1_metric < p2_metric + min_diff && + p1_metric > p2_metric - min_diff) { PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n", - p2_etx - min_diff, - p1_etx, - p2_etx + min_diff); + p2_metric - min_diff, + p1_metric, + p2_metric + min_diff); return dag->preferred_parent; } } - return p1_etx < p2_etx ? p1 : p2; + return p1_metric < p2_metric ? p1 : p2; } static void update_metric_container(rpl_dag_t *dag) { +#if RPL_DAG_MC == RPL_DAG_MC_ETX dag->mc.type = RPL_DAG_MC_ETX; dag->mc.flags = RPL_DAG_MC_FLAG_P; dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; dag->mc.prec = 0; - dag->mc.length = sizeof(dag->mc.etx.etx); + dag->mc.length = sizeof(dag->mc.obj.etx); if(dag->rank == ROOT_RANK(dag)) { - dag->mc.etx.etx = 0; + dag->mc.obj.etx = 0; } else { - dag->mc.etx.etx = calculate_etx(dag->preferred_parent); + dag->mc.obj.etx = calculate_path_metric(dag->preferred_parent); } +#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY + dag->mc.type = RPL_DAG_MC_ENERGY; + dag->mc.flags = RPL_DAG_MC_FLAG_P; + dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; + dag->mc.prec = 0; + dag->mc.length = sizeof(dag->mc.obj.energy); + if(dag->rank == ROOT_RANK(dag)) { + dag->mc.obj.energy.flags = RPL_DAG_MC_ENERGY_TYPE_MAINS << RPL_DAG_MC_ENERGY_TYPE; + } else { + dag->mc.obj.energy.flags = RPL_DAG_MC_ENERGY_TYPE_BATTERY << RPL_DAG_MC_ENERGY_TYPE; + } + dag->mc.obj.energy.energy_est = calculate_path_metric(dag->preferred_parent); +#else +#error "Unsupported RPL_DAG_MC configured. See rpl.h." +#endif /* RPL_DAG_MC */ PRINTF("RPL: My path ETX to the root is %u.%u\n", - dag->mc.etx.etx / RPL_DAG_MC_ETX_DIVISOR, - (dag->mc.etx.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); + dag->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, + (dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); } diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 17a1845ec..5676ccd31 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -49,6 +49,17 @@ #define RPL_CONF_STATS 0 #endif /* RPL_CONF_STATS */ +/* + * Select routing metric supported at runtime. This must be a valid + * DAG Metric Container Object Type (see below). Currently, we only + * support RPL_DAG_MC_ETX and RPL_DAG_MC_ENERGY. + */ +#ifdef RPL_CONF_DAG_MC +#define RPL_DAG_MC RPL_CONF_DAG_MC +#else +#define RPL_DAG_MC RPL_DAG_MC_ETX +#endif /* RPL_CONF_DAG_MC */ + /* * The objective function used by RPL is configurable through the * RPL_CONF_OF parameter. This should be defined to be the name of an @@ -78,8 +89,8 @@ typedef uint16_t rpl_ocp_t; /* DAG Metric Container Object Types, to be confirmed by IANA. */ #define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ #define RPL_DAG_MC_NSA 1 /* Node State and Attributes */ -#define RPL_DAG_MC_NE 2 /* Node Energy */ -#define RPL_DAG_MC_HC 3 /* Hop Count */ +#define RPL_DAG_MC_ENERGY 2 /* Node Energy */ +#define RPL_DAG_MC_HOPCOUNT 3 /* Hop Count */ #define RPL_DAG_MC_THROUGHPUT 4 /* Throughput */ #define RPL_DAG_MC_LATENCY 5 /* Latency */ #define RPL_DAG_MC_LQL 6 /* Link Quality Level */ @@ -99,9 +110,19 @@ typedef uint16_t rpl_ocp_t; #define RPL_DAG_MC_AGGR_MINIMUM 2 #define RPL_DAG_MC_AGGR_MULTIPLICATIVE 3 -/* Logical representation of an ETX object in a DAG Metric Container. */ -struct rpl_metric_object_etx { - uint16_t etx; +/* The bit index within the flags field of + the rpl_metric_object_energy structure. */ +#define RPL_DAG_MC_ENERGY_INCLUDED 3 +#define RPL_DAG_MC_ENERGY_TYPE 1 +#define RPL_DAG_MC_ENERGY_ESTIMATION 0 + +#define RPL_DAG_MC_ENERGY_TYPE_MAINS 0 +#define RPL_DAG_MC_ENERGY_TYPE_BATTERY 1 +#define RPL_DAG_MC_ENERGY_TYPE_SCAVENGING 2 + +struct rpl_metric_object_energy { + uint8_t flags; + uint8_t energy_est; }; /* Logical representation of a DAG Metric Container. */ @@ -111,9 +132,10 @@ struct rpl_metric_container { uint8_t aggr; uint8_t prec; uint8_t length; - /* Once we support more objects, the etx field will be replaced by a - union of those. */ - struct rpl_metric_object_etx etx; + union metric_object { + struct rpl_metric_object_energy energy; + uint16_t etx; + } obj; }; typedef struct rpl_metric_container rpl_metric_container_t; /*---------------------------------------------------------------------------*/