From a093c262ee7267141ed5947b83f7381fc7183178 Mon Sep 17 00:00:00 2001 From: nvt Date: Tue, 15 Feb 2011 01:13:30 +0100 Subject: [PATCH] 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. --- core/net/rpl/rpl-dag.c | 6 +++ core/net/rpl/rpl-icmp6.c | 51 +++++++++++++++++++++---- core/net/rpl/rpl-of-etx.c | 76 +++++++++++++++++++++++++------------- core/net/rpl/rpl-of0.c | 10 ++++- core/net/rpl/rpl-private.h | 41 +------------------- core/net/rpl/rpl.h | 53 ++++++++++++++++++++++++++ 6 files changed, 164 insertions(+), 73 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index c5c6e0fa8..4bace4074 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -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; diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 70a0e9bcf..d4963b79e 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -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; diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index a732cf662..d7e66b6af 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -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); +} diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index cc473faa6..b41f78791 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -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; +} diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 000f6b728..159beb12d 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -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; diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 6c37b85bb..660e5839a 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -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" */