Generalized MRHOF and added partial support for energy objects in DAG metric containers.
This commit is contained in:
parent
d9b5bac953
commit
4739143126
3 changed files with 79 additions and 34 deletions
|
@ -250,9 +250,10 @@ dio_input(void)
|
||||||
dio.mc.aggr = buffer[i + 4] >> 4;
|
dio.mc.aggr = buffer[i + 4] >> 4;
|
||||||
dio.mc.prec = buffer[i + 4] & 0xf;
|
dio.mc.prec = buffer[i + 4] & 0xf;
|
||||||
dio.mc.length = buffer[i + 5];
|
dio.mc.length = buffer[i + 5];
|
||||||
|
|
||||||
if(dio.mc.type == RPL_DAG_MC_ETX) {
|
if(dio.mc.type == RPL_DAG_MC_ETX) {
|
||||||
dio.mc.etx.etx = buffer[i + 6] << 8;
|
dio.mc.obj.etx = buffer[i + 6] << 8;
|
||||||
dio.mc.etx.etx |= buffer[i + 7];
|
dio.mc.obj.etx |= buffer[i + 7];
|
||||||
|
|
||||||
PRINTF("RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n",
|
PRINTF("RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n",
|
||||||
(unsigned)dio.mc.type,
|
(unsigned)dio.mc.type,
|
||||||
|
@ -260,7 +261,10 @@ dio_input(void)
|
||||||
(unsigned)dio.mc.aggr,
|
(unsigned)dio.mc.aggr,
|
||||||
(unsigned)dio.mc.prec,
|
(unsigned)dio.mc.prec,
|
||||||
(unsigned)dio.mc.length,
|
(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 {
|
} else {
|
||||||
PRINTF("RPL: Unhandled DAG MC type: %u\n", (unsigned)dio.mc.type);
|
PRINTF("RPL: Unhandled DAG MC type: %u\n", (unsigned)dio.mc.type);
|
||||||
return;
|
return;
|
||||||
|
@ -380,8 +384,12 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
|
||||||
buffer[pos++] |= dag->mc.prec;
|
buffer[pos++] |= dag->mc.prec;
|
||||||
if(dag->mc.type == RPL_DAG_MC_ETX) {
|
if(dag->mc.type == RPL_DAG_MC_ETX) {
|
||||||
buffer[pos++] = 2;
|
buffer[pos++] = 2;
|
||||||
buffer[pos++] = dag->mc.etx.etx >> 8;
|
buffer[pos++] = dag->mc.obj.etx >> 8;
|
||||||
buffer[pos++] = dag->mc.etx.etx & 0xff;
|
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 {
|
} else {
|
||||||
PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
|
PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
|
||||||
(unsigned)dag->mc.type);
|
(unsigned)dag->mc.type);
|
||||||
|
|
|
@ -66,7 +66,7 @@ rpl_of_t rpl_of_etx = {
|
||||||
|
|
||||||
#define NI_ETX_TO_RPL_ETX(etx) \
|
#define NI_ETX_TO_RPL_ETX(etx) \
|
||||||
((etx) * (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
|
((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))
|
((etx) / (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
|
||||||
|
|
||||||
/* Reject parents that have a higher link metric than the following. */
|
/* 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
|
#define PARENT_SWITCH_THRESHOLD_DIV 2
|
||||||
|
|
||||||
typedef uint16_t rpl_etx_t;
|
typedef uint16_t rpl_path_metric_t;
|
||||||
#define MAX_ETX 65535
|
|
||||||
|
|
||||||
static uint16_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
|
static void
|
||||||
|
@ -140,48 +139,64 @@ static rpl_parent_t *
|
||||||
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
rpl_etx_t min_diff;
|
rpl_path_metric_t min_diff;
|
||||||
rpl_etx_t p1_etx;
|
rpl_path_metric_t p1_metric;
|
||||||
rpl_etx_t p2_etx;
|
rpl_path_metric_t p2_metric;
|
||||||
|
|
||||||
dag = p1->dag; /* Both parents must be in the same DAG. */
|
dag = p1->dag; /* Both parents must be in the same DAG. */
|
||||||
|
|
||||||
min_diff = RPL_DAG_MC_ETX_DIVISOR /
|
min_diff = RPL_DAG_MC_ETX_DIVISOR /
|
||||||
PARENT_SWITCH_THRESHOLD_DIV;
|
PARENT_SWITCH_THRESHOLD_DIV;
|
||||||
|
|
||||||
p1_etx = calculate_etx(p1);
|
p1_metric = calculate_path_metric(p1);
|
||||||
p2_etx = calculate_etx(p2);
|
p2_metric = calculate_path_metric(p2);
|
||||||
|
|
||||||
/* Maintain stability of the preferred parent in case of similar ranks. */
|
/* Maintain stability of the preferred parent in case of similar ranks. */
|
||||||
if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
|
if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
|
||||||
if(p1_etx < p2_etx + min_diff &&
|
if(p1_metric < p2_metric + min_diff &&
|
||||||
p1_etx > p2_etx - min_diff) {
|
p1_metric > p2_metric - min_diff) {
|
||||||
PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n",
|
PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n",
|
||||||
p2_etx - min_diff,
|
p2_metric - min_diff,
|
||||||
p1_etx,
|
p1_metric,
|
||||||
p2_etx + min_diff);
|
p2_metric + min_diff);
|
||||||
return dag->preferred_parent;
|
return dag->preferred_parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return p1_etx < p2_etx ? p1 : p2;
|
return p1_metric < p2_metric ? p1 : p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_metric_container(rpl_dag_t *dag)
|
update_metric_container(rpl_dag_t *dag)
|
||||||
{
|
{
|
||||||
|
#if RPL_DAG_MC == RPL_DAG_MC_ETX
|
||||||
dag->mc.type = RPL_DAG_MC_ETX;
|
dag->mc.type = RPL_DAG_MC_ETX;
|
||||||
dag->mc.flags = RPL_DAG_MC_FLAG_P;
|
dag->mc.flags = RPL_DAG_MC_FLAG_P;
|
||||||
dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
||||||
dag->mc.prec = 0;
|
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)) {
|
if(dag->rank == ROOT_RANK(dag)) {
|
||||||
dag->mc.etx.etx = 0;
|
dag->mc.obj.etx = 0;
|
||||||
} else {
|
} 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",
|
PRINTF("RPL: My path ETX to the root is %u.%u\n",
|
||||||
dag->mc.etx.etx / RPL_DAG_MC_ETX_DIVISOR,
|
dag->mc.obj.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 * 100) / RPL_DAG_MC_ETX_DIVISOR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,17 @@
|
||||||
#define RPL_CONF_STATS 0
|
#define RPL_CONF_STATS 0
|
||||||
#endif /* RPL_CONF_STATS */
|
#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
|
* The objective function used by RPL is configurable through the
|
||||||
* RPL_CONF_OF parameter. This should be defined to be the name of an
|
* 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. */
|
/* 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_NONE 0 /* Local identifier for empty MC */
|
||||||
#define RPL_DAG_MC_NSA 1 /* Node State and Attributes */
|
#define RPL_DAG_MC_NSA 1 /* Node State and Attributes */
|
||||||
#define RPL_DAG_MC_NE 2 /* Node Energy */
|
#define RPL_DAG_MC_ENERGY 2 /* Node Energy */
|
||||||
#define RPL_DAG_MC_HC 3 /* Hop Count */
|
#define RPL_DAG_MC_HOPCOUNT 3 /* Hop Count */
|
||||||
#define RPL_DAG_MC_THROUGHPUT 4 /* Throughput */
|
#define RPL_DAG_MC_THROUGHPUT 4 /* Throughput */
|
||||||
#define RPL_DAG_MC_LATENCY 5 /* Latency */
|
#define RPL_DAG_MC_LATENCY 5 /* Latency */
|
||||||
#define RPL_DAG_MC_LQL 6 /* Link Quality Level */
|
#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_MINIMUM 2
|
||||||
#define RPL_DAG_MC_AGGR_MULTIPLICATIVE 3
|
#define RPL_DAG_MC_AGGR_MULTIPLICATIVE 3
|
||||||
|
|
||||||
/* Logical representation of an ETX object in a DAG Metric Container. */
|
/* The bit index within the flags field of
|
||||||
struct rpl_metric_object_etx {
|
the rpl_metric_object_energy structure. */
|
||||||
uint16_t etx;
|
#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. */
|
/* Logical representation of a DAG Metric Container. */
|
||||||
|
@ -111,9 +132,10 @@ struct rpl_metric_container {
|
||||||
uint8_t aggr;
|
uint8_t aggr;
|
||||||
uint8_t prec;
|
uint8_t prec;
|
||||||
uint8_t length;
|
uint8_t length;
|
||||||
/* Once we support more objects, the etx field will be replaced by a
|
union metric_object {
|
||||||
union of those. */
|
struct rpl_metric_object_energy energy;
|
||||||
struct rpl_metric_object_etx etx;
|
uint16_t etx;
|
||||||
|
} obj;
|
||||||
};
|
};
|
||||||
typedef struct rpl_metric_container rpl_metric_container_t;
|
typedef struct rpl_metric_container rpl_metric_container_t;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue