Generalized MRHOF and added partial support for energy objects in DAG metric containers.

This commit is contained in:
nvt 2011-03-15 01:16:20 +01:00
parent d9b5bac953
commit 4739143126
3 changed files with 79 additions and 34 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
/*---------------------------------------------------------------------------*/