Improved objective function API so DAG metric containers can be generated cleanly. The packet generation now asks the OF to provide a fresh logical presentation of the metric container, which is then translated to raw packet format.
This commit is contained in:
parent
20bf23cf06
commit
a093c262ee
6 changed files with 164 additions and 73 deletions
|
@ -189,6 +189,8 @@ rpl_set_root(uip_ipaddr_t *dag_id)
|
|||
dag->default_lifetime = DEFAULT_RPL_DEF_LIFETIME;
|
||||
dag->lifetime_unit = DEFAULT_RPL_LIFETIME_UNIT;
|
||||
|
||||
dag->of->update_metric_container(dag);
|
||||
|
||||
PRINTF("RPL: Node set to be a DAG root with DAG ID ");
|
||||
PRINT6ADDR(&dag->dag_id);
|
||||
PRINTF("\n");
|
||||
|
@ -300,6 +302,8 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
|
|||
p->etx = INITIAL_ETX;
|
||||
p->dtsn = 0;
|
||||
|
||||
memcpy(&p->mc, &dio->mc, sizeof(p->mc));
|
||||
|
||||
list_add(dag->parents, p);
|
||||
|
||||
return p;
|
||||
|
@ -337,6 +341,7 @@ rpl_select_parent(rpl_dag_t *dag)
|
|||
|
||||
if(dag->preferred_parent != best) {
|
||||
dag->preferred_parent = best; /* Cache the value. */
|
||||
dag->of->update_metric_container(dag);
|
||||
rpl_set_default_route(dag, &best->addr);
|
||||
/* The DAO parent set changed - schedule a DAO transmission. */
|
||||
rpl_schedule_dao(dag);
|
||||
|
@ -482,6 +487,7 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
|
||||
dag->version = dio->version;
|
||||
dag->preferred_parent = p;
|
||||
dag->of->update_metric_container(dag);
|
||||
|
||||
dag->dio_intdoubl = dio->dag_intdoubl;
|
||||
dag->dio_intmin = dio->dag_intmin;
|
||||
|
|
|
@ -236,6 +236,8 @@ dio_input(void)
|
|||
return;
|
||||
}
|
||||
|
||||
PRINTF("RPL: DIO suboption %u, length: %u\n", subopt_type, len - 2);
|
||||
|
||||
switch(subopt_type) {
|
||||
case RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER:
|
||||
if(len < 6) {
|
||||
|
@ -243,13 +245,25 @@ dio_input(void)
|
|||
RPL_STAT(rpl_stats.malformed_msgs++);
|
||||
return;
|
||||
}
|
||||
dio.metric_container.type = buffer[i + 2];
|
||||
dio.metric_container.flags = buffer[i + 3];
|
||||
dio.metric_container.aggr = buffer[i + 4] >> 4;
|
||||
dio.metric_container.prec = buffer[i + 4] & 0xf;
|
||||
dio.metric_container.length = buffer[i + 5];
|
||||
if(dio.metric_container.type == RPL_DAG_MC_ETX) {
|
||||
dio.metric_container.etx.etx = buffer[i + 6];
|
||||
dio.mc.type = buffer[i + 2];
|
||||
dio.mc.flags = buffer[i + 3];
|
||||
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];
|
||||
|
||||
PRINTF("RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n",
|
||||
(unsigned)dio.mc.type,
|
||||
(unsigned)dio.mc.flags,
|
||||
(unsigned)dio.mc.aggr,
|
||||
(unsigned)dio.mc.prec,
|
||||
(unsigned)dio.mc.length,
|
||||
(unsigned)dio.mc.etx.etx);
|
||||
} else {
|
||||
PRINTF("RPL: Unhandled DAG MC type: %u\n", (unsigned)dio.mc.type);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case RPL_DIO_SUBOPT_ROUTE_INFO:
|
||||
|
@ -313,6 +327,9 @@ dio_input(void)
|
|||
PRINTF("RPL: Copying prefix information\n");
|
||||
memcpy(&dio.prefix_info.prefix, &buffer[i + 16], 16);
|
||||
break;
|
||||
default:
|
||||
PRINTF("RPL: Unsupported suboption type in DIO: %u\n",
|
||||
(unsigned)subopt_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +369,26 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
|
|||
memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id));
|
||||
pos += 16;
|
||||
|
||||
if(dag->mc.type != RPL_DAG_MC_NONE) {
|
||||
dag->of->update_metric_container(dag);
|
||||
|
||||
buffer[pos++] = RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER;
|
||||
buffer[pos++] = 6;
|
||||
buffer[pos++] = dag->mc.type;
|
||||
buffer[pos++] = dag->mc.flags;
|
||||
buffer[pos] = dag->mc.aggr << 4;
|
||||
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;
|
||||
} else {
|
||||
PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
|
||||
(unsigned)dag->mc.type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* always add a sub-option for DAG configuration */
|
||||
buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF;
|
||||
buffer[pos++] = 14;
|
||||
|
|
|
@ -53,15 +53,22 @@ static void reset(rpl_dag_t *);
|
|||
static void parent_state_callback(rpl_parent_t *, int, int);
|
||||
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
||||
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
||||
static void update_metric_container(rpl_dag_t *);
|
||||
|
||||
rpl_of_t rpl_of_etx = {
|
||||
reset,
|
||||
parent_state_callback,
|
||||
best_parent,
|
||||
calculate_rank,
|
||||
update_metric_container,
|
||||
1
|
||||
};
|
||||
|
||||
#define NI_ETX_TO_RPL_ETX(etx) \
|
||||
((etx) * (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
|
||||
#define RPL_ETX_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. */
|
||||
#define MAX_LINK_METRIC 10
|
||||
|
||||
|
@ -77,15 +84,21 @@ rpl_of_t rpl_of_etx = {
|
|||
*/
|
||||
#define PARENT_SWITCH_THRESHOLD_DIV 2
|
||||
|
||||
#define MAX_DIFFERENCE(dag) \
|
||||
((dag)->min_hoprankinc / PARENT_SWITCH_THRESHOLD_DIV)
|
||||
typedef uint16_t rpl_etx_t;
|
||||
#define MAX_ETX 65535
|
||||
|
||||
static rpl_rank_t min_path_cost = INFINITE_RANK;
|
||||
static rpl_etx_t min_path_cost = MAX_ETX;
|
||||
|
||||
static uint16_t
|
||||
calculate_etx(rpl_parent_t *p)
|
||||
{
|
||||
return p->mc.etx.etx + NI_ETX_TO_RPL_ETX(p->etx);
|
||||
}
|
||||
|
||||
static void
|
||||
reset(rpl_dag_t *dag)
|
||||
{
|
||||
min_path_cost = INFINITE_RANK;
|
||||
min_path_cost = MAX_ETX;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -120,14 +133,6 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
|||
}
|
||||
}
|
||||
|
||||
PRINTF("RPL: MRHOF calculate rank, base rank = %u, rank_increase = %u\n",
|
||||
(unsigned)base_rank, rank_increase);
|
||||
|
||||
if(base_rank < min_path_cost) {
|
||||
min_path_cost = base_rank;
|
||||
PRINTF("RPL: min_path_cost updated to %u\n", min_path_cost);
|
||||
}
|
||||
|
||||
if(INFINITE_RANK - base_rank < rank_increase) {
|
||||
/* Reached the maximum rank. */
|
||||
new_rank = INFINITE_RANK;
|
||||
|
@ -137,8 +142,6 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
|||
new_rank = base_rank + rank_increase;
|
||||
}
|
||||
|
||||
PRINTF("RPL: Path cost %u\n", (unsigned)new_rank);
|
||||
|
||||
return new_rank;
|
||||
}
|
||||
|
||||
|
@ -146,27 +149,50 @@ static rpl_parent_t *
|
|||
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||
{
|
||||
rpl_dag_t *dag;
|
||||
rpl_rank_t p1_rank;
|
||||
rpl_rank_t p2_rank;
|
||||
rpl_etx_t min_diff;
|
||||
rpl_etx_t p1_etx;
|
||||
rpl_etx_t p2_etx;
|
||||
|
||||
dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */
|
||||
dag = p1->dag; /* Both parents must be in the same DAG. */
|
||||
|
||||
p1_rank = calculate_rank(p1, 0);
|
||||
p2_rank = calculate_rank(p2, 0);
|
||||
min_diff = RPL_DAG_MC_ETX_DIVISOR /
|
||||
PARENT_SWITCH_THRESHOLD_DIV;
|
||||
|
||||
p1_etx = calculate_etx(p1);
|
||||
p2_etx = calculate_etx(p2);
|
||||
|
||||
/* Maintain stability of the preferred parent in case of similar ranks. */
|
||||
if(p1_rank < p2_rank + MAX_DIFFERENCE(dag) &&
|
||||
p1_rank > p2_rank - MAX_DIFFERENCE(dag)) {
|
||||
if(p1_etx < p2_etx + min_diff &&
|
||||
p1_etx > p2_etx - min_diff) {
|
||||
PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n",
|
||||
p2_rank - MAX_DIFFERENCE(dag),
|
||||
p1_rank,
|
||||
p2_rank + MAX_DIFFERENCE(dag));
|
||||
p2_etx - min_diff,
|
||||
p1_etx,
|
||||
p2_etx + min_diff);
|
||||
return dag->preferred_parent;
|
||||
}
|
||||
|
||||
if(p1_rank < p2_rank) {
|
||||
if(p1_etx < p2_etx) {
|
||||
return p1;
|
||||
}
|
||||
|
||||
return p2;
|
||||
}
|
||||
|
||||
static void
|
||||
update_metric_container(rpl_dag_t *dag)
|
||||
{
|
||||
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);
|
||||
if(dag->rank == ROOT_RANK) {
|
||||
dag->mc.etx.etx = 0;
|
||||
} else {
|
||||
dag->mc.etx.etx = calculate_etx(dag->preferred_parent);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "net/rpl/rpl-private.h"
|
||||
|
||||
#define DEBUG DEBUG_ANNOTATE
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/uip-debug.h"
|
||||
|
||||
#include "net/neighbor-info.h"
|
||||
|
@ -49,12 +49,14 @@
|
|||
static void reset(rpl_dag_t *);
|
||||
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
||||
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
||||
static void update_metric_container(rpl_dag_t *);
|
||||
|
||||
rpl_of_t rpl_of0 = {
|
||||
reset,
|
||||
NULL,
|
||||
best_parent,
|
||||
calculate_rank,
|
||||
update_metric_container,
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -123,3 +125,9 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
|||
return p2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_metric_container(rpl_dag_t *dag)
|
||||
{
|
||||
dag->mc.type = RPL_DAG_MC_NONE;
|
||||
}
|
||||
|
|
|
@ -158,28 +158,6 @@
|
|||
#define RPL_MOP_STORING_MULTICAST 3
|
||||
#define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST
|
||||
|
||||
/* DAG Metric Container Object Types, to be confirmed by IANA. */
|
||||
#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_THROUGHPUT 4 /* Throughput */
|
||||
#define RPL_DAG_MC_LATENCY 5 /* Latency */
|
||||
#define RPL_DAG_MC_LQL 6 /* Link Quality Level */
|
||||
#define RPL_DAG_MC_ETX 7 /* Expected Transmission Count */
|
||||
#define RPL_DAG_MC_LC 8 /* Link Color */
|
||||
|
||||
/* DAG Metric Container flags. */
|
||||
#define RPL_DAG_MC_FLAG_P 0x8
|
||||
#define RPL_DAG_MC_FLAG_C 0x4
|
||||
#define RPL_DAG_MC_FLAG_O 0x2
|
||||
#define RPL_DAG_MC_FLAG_R 0x1
|
||||
|
||||
/* DAG Metric Container aggregation mode. */
|
||||
#define RPL_DAG_MC_AGGR_ADDITIVE 0
|
||||
#define RPL_DAG_MC_AGGR_MAXIMUM 1
|
||||
#define RPL_DAG_MC_AGGR_MINIMUM 2
|
||||
#define RPL_DAG_MC_AGGR_MULTIPLICATIVE 3
|
||||
|
||||
/*
|
||||
* The ETX in the metric container is expressed as a fixed-point value
|
||||
* whose integer part can be obtained by dividing the value by
|
||||
|
@ -196,23 +174,6 @@
|
|||
#endif
|
||||
#define RPL_DIS_START_DELAY 5
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Logical representation of an ETX object in a DAG Metric Container. */
|
||||
struct rpl_metric_object_etx {
|
||||
uint16_t etx;
|
||||
};
|
||||
|
||||
/* Logical representation of a DAG Metric Container. */
|
||||
struct rpl_metric_container {
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
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;
|
||||
};
|
||||
|
||||
/* Logical representation of a DAG Information Object (DIO.) */
|
||||
struct rpl_dio {
|
||||
uip_ipaddr_t dag_id;
|
||||
|
@ -233,7 +194,7 @@ struct rpl_dio {
|
|||
rpl_rank_t dag_min_hoprankinc;
|
||||
rpl_prefix_t destination_prefix;
|
||||
rpl_prefix_t prefix_info;
|
||||
struct rpl_metric_container metric_container;
|
||||
struct rpl_metric_container mc;
|
||||
};
|
||||
typedef struct rpl_dio rpl_dio_t;
|
||||
|
||||
|
|
|
@ -74,11 +74,55 @@
|
|||
typedef uint16_t rpl_rank_t;
|
||||
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_THROUGHPUT 4 /* Throughput */
|
||||
#define RPL_DAG_MC_LATENCY 5 /* Latency */
|
||||
#define RPL_DAG_MC_LQL 6 /* Link Quality Level */
|
||||
#define RPL_DAG_MC_ETX 7 /* Expected Transmission Count
|
||||
*/
|
||||
#define RPL_DAG_MC_LC 8 /* Link Color */
|
||||
|
||||
/* DAG Metric Container flags. */
|
||||
#define RPL_DAG_MC_FLAG_P 0x8
|
||||
#define RPL_DAG_MC_FLAG_C 0x4
|
||||
#define RPL_DAG_MC_FLAG_O 0x2
|
||||
#define RPL_DAG_MC_FLAG_R 0x1
|
||||
|
||||
/* DAG Metric Container aggregation mode. */
|
||||
#define RPL_DAG_MC_AGGR_ADDITIVE 0
|
||||
#define RPL_DAG_MC_AGGR_MAXIMUM 1
|
||||
#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;
|
||||
};
|
||||
|
||||
/* Logical representation of a DAG Metric Container. */
|
||||
struct rpl_metric_container {
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
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;
|
||||
};
|
||||
typedef struct rpl_metric_container rpl_metric_container_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct rpl_dag;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct rpl_parent {
|
||||
struct rpl_parent *next;
|
||||
struct rpl_dag *dag;
|
||||
rpl_metric_container_t mc;
|
||||
uip_ipaddr_t addr;
|
||||
rpl_rank_t rank;
|
||||
uint8_t etx;
|
||||
|
@ -111,12 +155,20 @@ typedef struct rpl_parent rpl_parent_t;
|
|||
* If "parent" is NULL, the objective function selects a default increment
|
||||
* that is adds to the "base_rank". Otherwise, the OF uses information known
|
||||
* about "parent" to select an increment to the "base_rank".
|
||||
*
|
||||
* update_metric_container(dag)
|
||||
*
|
||||
* Updates the metric container for outgoing DIOs in a certain DAG.
|
||||
* If the objective function of the DAG does not use metric containers,
|
||||
* the function returns 0. If the metric container has been filled, the
|
||||
* function returns 1.
|
||||
*/
|
||||
struct rpl_of {
|
||||
void (*reset)(struct rpl_dag *);
|
||||
void (*parent_state_callback)(rpl_parent_t *, int, int);
|
||||
rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *);
|
||||
rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t);
|
||||
void (*update_metric_container)(struct rpl_dag *);
|
||||
rpl_ocp_t ocp;
|
||||
};
|
||||
typedef struct rpl_of rpl_of_t;
|
||||
|
@ -133,6 +185,7 @@ typedef struct rpl_prefix rpl_prefix_t;
|
|||
/* Directed Acyclic Graph */
|
||||
struct rpl_dag {
|
||||
/* DAG configuration */
|
||||
rpl_metric_container_t mc;
|
||||
rpl_of_t *of;
|
||||
uip_ipaddr_t dag_id;
|
||||
/* The current default router - used for routing "upwards" */
|
||||
|
|
Loading…
Reference in a new issue