From fec0e8df697063dc01b90c05cf46c99ad1484faf Mon Sep 17 00:00:00 2001 From: joxe Date: Tue, 1 Jun 2010 22:30:02 +0000 Subject: [PATCH] changed RPL to be more 08 compliant - DIO and DIO options are formatted as in RPL-08 --- core/net/rpl/rpl-dag.c | 18 ++--- core/net/rpl/rpl-icmp6.c | 166 ++++++++++++++++++++++----------------- core/net/rpl/rpl.h | 42 ++++++++-- 3 files changed, 138 insertions(+), 88 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index e4fe78596..aa68d65a8 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-dag.c,v 1.11 2010/05/31 14:22:00 nvt-se Exp $ + * $Id: rpl-dag.c,v 1.12 2010/06/01 22:30:02 joxe Exp $ */ /** * \file @@ -149,6 +149,8 @@ rpl_set_root(uip_ipaddr_t *dag_id) dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY; + dag->max_rankinc = DEFAULT_MAX_RANKINC; + dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; PRINTF("RPL: Node set to be a DAG root with DAG ID "); PRINT6ADDR(&dag->dag_id); @@ -162,13 +164,10 @@ rpl_set_root(uip_ipaddr_t *dag_id) int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) { if(len <= 128) { - memset(&dag->destination_prefix.prefix, 0, 16); - memcpy(&dag->destination_prefix.prefix, prefix, (len + 7)/ 8); - dag->destination_prefix.length = len; - /* Note: this is an experiment to see if RPL can be used for - prefix-assignment for RPL nodes - this flag is originally - intended for Router Advertisements */ - dag->destination_prefix.preference = UIP_ND6_RA_FLAG_AUTONOMOUS; + memset(&dag->prefix_info.prefix, 0, 16); + memcpy(&dag->prefix_info.prefix, prefix, (len + 7)/ 8); + dag->prefix_info.length = len; + dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS; PRINTF("RPL: Prefix set - will announce this in DIOs\n"); return 0; } @@ -428,8 +427,7 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* copy prefix information into the dag */ - memcpy(&dag->destination_prefix, &dio->destination_prefix, - sizeof(rpl_prefix_t)); + memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_join_dag(dag); diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index bed435bc1..649e9da00 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-icmp6.c,v 1.12 2010/05/29 22:23:21 nvt-se Exp $ + * $Id: rpl-icmp6.c,v 1.13 2010/06/01 22:30:02 joxe Exp $ */ /** * \file @@ -62,7 +62,9 @@ #define RPL_DIO_GROUNDED 0x80 #define RPL_DIO_DEST_ADV_SUPPORTED 0x40 #define RPL_DIO_DEST_ADV_TRIGGER 0x20 -#define RPL_DIO_DEST_ADV_STORED 0x10 +#define RPL_DIO_MOP_MASK 0x18 +#define RPL_DIO_MOP_NON_STORING 0x00 +#define RPL_DIO_MOP_STORING 0x10 #define RPL_DIO_DAG_PREFERENCE_MASK 0x07 @@ -200,16 +202,20 @@ dio_input(void) /* Process the DIO base option. */ i = 0; buffer = UIP_ICMP_PAYLOAD; + + dio.instance_id = buffer[i++]; + dio.version = buffer[i++]; + dio.dag_rank = (buffer[i] << 8) + buffer[i + 1]; + i += 2; + dio.grounded = buffer[i] & RPL_DIO_GROUNDED; dio.dst_adv_trigger = buffer[i] & RPL_DIO_DEST_ADV_TRIGGER; dio.dst_adv_supported = buffer[i] & RPL_DIO_DEST_ADV_SUPPORTED; dio.preference = buffer[i++] & RPL_DIO_DAG_PREFERENCE_MASK; - dio.sequence_number = buffer[i++]; - dio.dag_rank = (buffer[i] << 8) + buffer[i + 1]; - i += 2; - dio.instance_id = buffer[i++]; dio.dtsn = buffer[i++]; + /* two reserved bytes */ + i += 2; memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id)); i += sizeof(dio.dag_id); @@ -220,8 +226,8 @@ dio_input(void) if(subopt_type == RPL_DIO_SUBOPT_PAD1) { len = 1; } else { - /* Suboption with a three-byte header. */ - len = (buffer[i + 1] << 8) + buffer[i + 2] + 3; + /* Suboption with a two-byte header + payload */ + len = 2 + buffer[i + 1]; } switch(subopt_type) { @@ -231,58 +237,74 @@ dio_input(void) return; } break; - case RPL_DIO_SUBOPT_DEST_PREFIX: + case RPL_DIO_SUBOPT_ROUTE_INFO: if(len < 9) { PRINTF("RPL: Invalid destination prefix option, len = %d\n", len); return; } - /* prebference is both preference and flags for now */ - dio.destination_prefix.preference = buffer[i + 3]; + /* flags is both preference and flags for now */ + dio.destination_prefix.length = buffer[i + 2]; + dio.destination_prefix.flags = buffer[i + 3]; dio.destination_prefix.lifetime = get32(buffer, i + 4); - dio.destination_prefix.length = buffer[i + 8]; - if(((dio.destination_prefix.length + 7)/ 8) + 9 <= len && + + if(((dio.destination_prefix.length + 7)/ 8) + 8 <= len && dio.destination_prefix.length <= 128) { PRINTF("RPL: Copying destination prefix\n"); - memcpy(&dio.destination_prefix.prefix, &buffer[i + 9], + memcpy(&dio.destination_prefix.prefix, &buffer[i + 8], (dio.destination_prefix.length + 7) / 8); - - /* NOTE: This is a test for adding autoconf prefix in RPL via */ - /* a destination prefix - this use one reserved flag bit */ - /* This should not be made until RPL decides to join the DAG */ - /* And not if there already is a global address configured for */ - /* the specific DAG */ - if((dio.destination_prefix.preference & UIP_ND6_RA_FLAG_AUTONOMOUS)) { - uip_ipaddr_t ipaddr; - memcpy(&ipaddr, &dio.destination_prefix.prefix, - (dio.destination_prefix.length + 7) / 8); - uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); - if(uip_ds6_addr_lookup(&ipaddr) == NULL) { - PRINTF("RPL: adding global IP address "); - PRINT6ADDR(&ipaddr); - PRINTF("\n"); - uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); - } - } } else { - PRINTF("RPL: Invalid destination prefix option, len = %d\n", len); + PRINTF("RPL: Invalid route infoprefix option, len = %d\n", len); } break; case RPL_DIO_SUBOPT_DAG_CONF: + /* Path control field not yet implemented - at i + 2 */ dio.dag_intdoubl = buffer[i + 3]; dio.dag_intmin = buffer[i + 4]; dio.dag_redund = buffer[i + 5]; - dio.dag_max_rankinc = buffer[i + 6]; - dio.dag_min_hoprankinc = buffer[i + 7]; + dio.dag_max_rankinc = (buffer[i + 6] << 8) | buffer[i + 7]; + dio.dag_min_hoprankinc = (buffer[i + 8] << 8) | buffer[i + 9]; PRINTF("RPL: DIO trickle timer:dbl=%d, min=%d red=%d maxinc=%d mininc=%d\n", - dio.dag_intdoubl, + dio.dag_intdoubl, dio.dag_intmin, dio.dag_redund, dio.dag_max_rankinc, dio.dag_min_hoprankinc); break; case RPL_DIO_SUBOPT_OCP: - dio.ocp = buffer[i + 3] << 8 | buffer[i + 4]; + dio.ocp = buffer[i + 2] << 8 | buffer[i + 3]; PRINTF("RPL: DAG OCP Sub-opt received OCP = %u\n", dio.ocp); break; + case RPL_DIO_SUBOPT_PREFIX_INFO: + if(len != 32) { + PRINTF("RPL: DAG Prefix info not ok, len != 32\n"); + return; + } + dio.prefix_info.length = buffer[i + 2]; + dio.prefix_info.flags = buffer[i + 3]; + /* valid lifetime is ingnored for now - at i + 4 */ + /* preferred lifetime stored in lifetime */ + dio.prefix_info.lifetime = get32(buffer, i + 8); + /* 32-bit reserved at i + 12 */ + PRINTF("RPL: Copying prefix information\n"); + memcpy(&dio.prefix_info.prefix, &buffer[i + 16], 16); + + /* NOTE: This is a test for adding autoconf prefix in RPL via */ + /* a destination prefix - this use one reserved flag bit */ + /* This should not be made until RPL decides to join the DAG */ + /* And not if there already is a global address configured for */ + /* the specific DAG */ + if((dio.prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) { + uip_ipaddr_t ipaddr; + /* assume that the prefix ends with zeros! */ + memcpy(&ipaddr, &dio.prefix_info.prefix, 16); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + if(uip_ds6_addr_lookup(&ipaddr) == NULL) { + PRINTF("RPL: adding global IP address "); + PRINT6ADDR(&ipaddr); + PRINTF("\n"); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + } + } + break; } } @@ -301,27 +323,27 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) pos = 0; buffer = UIP_ICMP_PAYLOAD; - buffer[0] = dag->preference; - if(dag->grounded) { - buffer[0] |= RPL_DIO_GROUNDED; - } - /* Set dst_adv_trigger and dst_adv_supported. */ - buffer[0] |= RPL_DIO_DEST_ADV_SUPPORTED | RPL_DIO_DEST_ADV_TRIGGER; - - buffer[1] = dag->sequence_number; - - pos = 2; + buffer[pos++] = dag->instance_id; + buffer[pos++] = 0; /* version */ buffer[pos++] = dag->rank >> 8; buffer[pos++] = dag->rank & 0xff; - buffer[pos++] = dag->instance_id; + + if(dag->grounded) { + buffer[pos] |= RPL_DIO_GROUNDED; + } + /* Set dst_adv_trigger and dst_adv_supported. */ + buffer[pos] |= RPL_DIO_DEST_ADV_SUPPORTED | RPL_DIO_DEST_ADV_TRIGGER; + pos++; + /* buffer[pos++] = dag->sequence_number; */ buffer[pos++] = dag->dtsn; + /* reserved 2 bytes */ + pos += 2; memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos += 16; /* The objective function object must appear first. */ buffer[pos++] = RPL_DIO_SUBOPT_OCP; - buffer[pos++] = 0; buffer[pos++] = 2; buffer[pos++] = dag->of->ocp >> 8; buffer[pos++] = dag->of->ocp & 0xff; @@ -330,32 +352,36 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) /* always add a sub-option for DAG configuration */ buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF; - buffer[pos++] = 0; - buffer[pos++] = 5; + buffer[pos++] = 8; + buffer[pos++] = 0; /* PCS */ buffer[pos++] = dag->dio_intdoubl; buffer[pos++] = dag->dio_intmin; buffer[pos++] = dag->dio_redundancy; - buffer[pos++] = dag->max_rankinc; - buffer[pos++] = dag->min_hoprankinc; + buffer[pos++] = dag->max_rankinc >> 8; + buffer[pos++] = dag->max_rankinc & 0xff; + buffer[pos++] = dag->min_hoprankinc >> 8; + buffer[pos++] = dag->min_hoprankinc & 0xff; - /* if prefix length > 0 then we have a prefix to send! */ - if(dag->destination_prefix.length > 0) { - buffer[pos++] = RPL_DIO_SUBOPT_DEST_PREFIX; - buffer[pos++] = 0; - buffer[pos++] = (dag->destination_prefix.length + 7)/ 8 + 9; - buffer[pos++] = dag->destination_prefix.preference; - set32(buffer, pos, dag->destination_prefix.lifetime); + /* if prefix info length > 0 then we have a prefix to send! */ + if(dag->prefix_info.length > 0) { + buffer[pos++] = RPL_DIO_SUBOPT_PREFIX_INFO; + buffer[pos++] = 30; /* always 30 bytes + 2 long */ + buffer[pos++] = dag->prefix_info.length; + buffer[pos++] = dag->prefix_info.flags; + set32(buffer, pos, dag->prefix_info.lifetime); pos += 4; - buffer[pos++] = dag->destination_prefix.length; - memcpy(&buffer[pos], &(dag->destination_prefix.prefix), - (dag->destination_prefix.length + 7)/ 8); - pos += (dag->destination_prefix.length + 7)/ 8; + set32(buffer, pos, dag->prefix_info.lifetime); + pos += 4; + memset(&buffer[pos], 0, 4); + pos += 4; + memcpy(&buffer[pos], &(dag->prefix_info.prefix), 16); + pos += 16; PRINTF("RPL: Sending prefix info in DIO "); - PRINT6ADDR(&dag->destination_prefix.prefix); + PRINT6ADDR(&dag->prefix_info.prefix); PRINTF("\n"); } else { PRINTF("RPL: No prefix to announce. len:%d\n", - dag->destination_prefix.length); + dag->prefix_info.length); } /* buffer[len++] = RPL_DIO_SUBOPT_PAD1; */ @@ -363,12 +389,12 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) /* Unicast requests get unicast replies! */ if(uc_addr == NULL) { PRINTF("RPL: Sending a multicast-DIO with rank %u\n", - (unsigned)dag->rank); + (unsigned)dag->rank); uip_create_linklocal_allrouters_mcast(&addr); uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos); } else { PRINTF("RPL: Sending unicast-DIO with rank %u to ", - (unsigned)dag->rank); + (unsigned)dag->rank); PRINT6ADDR(uc_addr); PRINTF("\n"); uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos); @@ -425,7 +451,7 @@ dao_input(void) if(rank < dag->rank) { PRINTF("RPL: Incoming DAO rank is %u, my rank is %u\n", - (unsigned)rank, (unsigned)dag->rank); + (unsigned)rank, (unsigned)dag->rank); return; } @@ -433,7 +459,7 @@ dao_input(void) memcpy(&prefix, buffer + pos, prefixlen / CHAR_BIT); PRINTF("RPL: DAO rank: %u, lifetime: %lu, prefix length: %u", - (unsigned)rank, (unsigned long)lifetime, (unsigned)prefixlen); + (unsigned)rank, (unsigned long)lifetime, (unsigned)prefixlen); PRINTF("\n"); if(lifetime == ZERO_LIFETIME) { diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 79fe7564d..f203a3cc9 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -30,12 +30,25 @@ * * Author: Joakim Eriksson, Nicolas Tsiftes * - * $Id: rpl.h,v 1.6 2010/05/31 14:22:00 nvt-se Exp $ + * $Id: rpl.h,v 1.7 2010/06/01 22:30:02 joxe Exp $ */ #ifndef RPL_H #define RPL_H +/* + * ContikiRPL - an implementation of the routing protocol for low power and + * lossy networks. See: draft-ietf-roll-rpl-08. + * + * Note: This version of ContikiRPL is currently moving on to RPL-08, but + * since the type of the OCP option for DIOs is unclear we assume that it + * will be of type 9. + * -- + * The DIOs handle prefix information option for setting global IP addresses + * on the nodes, but the current handling is not awaiting the join of the DAG + * so it does not currently support multiple DAGs. + */ + #include "lib/list.h" #include "net/uip.h" #include "sys/clock.h" @@ -48,17 +61,28 @@ #endif /* RPL_CONF_STATS */ /* The RPL Codes for the message types */ -#define RPL_CODE_DIS 1 /* DIS message */ -#define RPL_CODE_DIO 2 /* DIO message */ -#define RPL_CODE_DAO 4 /* DAO message */ +#define RPL_CODE_DIS 0 /* DIS message */ +#define RPL_CODE_DIO 1 /* DIO message */ +#define RPL_CODE_DAO 2 /* DAO message */ +#define RPL_CODE_DAO_ACK 3 /* DAO ACK message */ + +#define RPL_CODE_SEC_DIS 0x80 /* DIS message */ +#define RPL_CODE_SEC_DIO 0x81 /* DIO message */ +#define RPL_CODE_SEC_DAO 0x82 /* DAO message */ +#define RPL_CODE_SEC_DAO_ACK 0x83 /* DAO ACK message */ /* RPL DIO suboption types */ #define RPL_DIO_SUBOPT_PAD1 0 /* Pad1 */ #define RPL_DIO_SUBOPT_PADN 1 /* PadN */ #define RPL_DIO_SUBOPT_DAG_MC 2 /* DAG metric container */ -#define RPL_DIO_SUBOPT_DEST_PREFIX 3 /* Destination prefix */ +#define RPL_DIO_SUBOPT_ROUTE_INFO 3 /* Route information */ #define RPL_DIO_SUBOPT_DAG_CONF 4 /* DAG configuration */ -#define RPL_DIO_SUBOPT_OCP 5 /* OCP */ +#define RPL_DIO_SUBOPT_TARGET 5 /* Target */ +#define RPL_DIO_SUBOPT_TRANSIT 6 /* Transit information */ +#define RPL_DIO_SUBOPT_SOLICITED_INFO 7 /* Solicited information */ +#define RPL_DIO_SUBOPT_PREFIX_INFO 8 /* Prefix information option */ + +#define RPL_DIO_SUBOPT_OCP 9 /* 5 in the MC document... */ /*---------------------------------------------------------------------------*/ /* Default values for RPL constants and variables. */ @@ -153,7 +177,7 @@ struct rpl_prefix { uip_ipaddr_t prefix; uint32_t lifetime; uint8_t length; - uint8_t preference; + uint8_t flags; }; typedef struct rpl_prefix rpl_prefix_t; @@ -167,6 +191,7 @@ struct rpl_dio { uint8_t dst_adv_trigger; uint8_t dst_adv_supported; uint8_t preference; + uint8_t version; uint8_t sequence_number; uint8_t instance_id; uint8_t dtsn; @@ -176,6 +201,7 @@ struct rpl_dio { uint8_t dag_max_rankinc; uint8_t dag_min_hoprankinc; rpl_prefix_t destination_prefix; + rpl_prefix_t prefix_info; }; typedef struct rpl_dio rpl_dio_t; @@ -217,7 +243,7 @@ struct rpl_dag { rpl_parent_t *best_parent; void *parent_list; list_t parents; - rpl_prefix_t destination_prefix; + rpl_prefix_t prefix_info; }; typedef struct rpl_dag rpl_dag_t;