Changes in RPL implementation :
- Structural modification of RPL data storage. - Support multiple gateways (multiple DODAG-ID with a unique InstanceID) - Use Lollipop counters - Add leaf-only configuration option for RPL Bugfix : - Correctly send "Grounded" flag in DIO
This commit is contained in:
parent
2ac91d53b5
commit
dc9cbe647d
15 changed files with 1497 additions and 555 deletions
File diff suppressed because it is too large
Load diff
|
@ -72,7 +72,7 @@ static void dio_input(void);
|
||||||
static void dao_input(void);
|
static void dao_input(void);
|
||||||
static void dao_ack_input(void);
|
static void dao_ack_input(void);
|
||||||
|
|
||||||
static uint8_t dao_sequence;
|
static uint8_t dao_sequence = RPL_LOLLIPOP_INIT;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
get_global_addr(uip_ipaddr_t *addr)
|
get_global_addr(uip_ipaddr_t *addr)
|
||||||
|
@ -112,21 +112,27 @@ set32(uint8_t *buffer, int pos, uint32_t value)
|
||||||
static void
|
static void
|
||||||
dis_input(void)
|
dis_input(void)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_instance_t *instance;
|
||||||
|
rpl_instance_t *end;
|
||||||
|
|
||||||
/* DAG Information Solicitation */
|
/* DAG Information Solicitation */
|
||||||
PRINTF("RPL: Received a DIS from ");
|
PRINTF("RPL: Received a DIS from ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||||
if(dag != NULL) {
|
if ( instance->used == 1 ) {
|
||||||
|
#if RPL_LEAF_ONLY
|
||||||
|
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||||
|
#else /* !RPL_LEAF_ONLY */
|
||||||
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||||
PRINTF("RPL: Multicast DIS => reset DIO timer\n");
|
PRINTF("RPL: Multicast DIS => reset DIO timer\n");
|
||||||
rpl_reset_dio_timer(dag, 0);
|
rpl_reset_dio_timer(instance, 0);
|
||||||
} else {
|
} else {
|
||||||
|
#endif /* !RPL_LEAF_ONLY */
|
||||||
PRINTF("RPL: Unicast DIS, reply to sender\n");
|
PRINTF("RPL: Unicast DIS, reply to sender\n");
|
||||||
dio_output(dag, &UIP_IP_BUF->srcipaddr);
|
dio_output(instance, &UIP_IP_BUF->srcipaddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +205,7 @@ dio_input(void)
|
||||||
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
||||||
|
|
||||||
#if RPL_CONF_ADJUST_LLH_LEN
|
#if RPL_CONF_ADJUST_LLH_LEN
|
||||||
buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header
|
buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Process the DIO base option. */
|
/* Process the DIO base option. */
|
||||||
|
@ -211,6 +217,7 @@ dio_input(void)
|
||||||
dio.rank = (buffer[i] << 8) | buffer[i + 1];
|
dio.rank = (buffer[i] << 8) | buffer[i + 1];
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
|
PRINTF("RPL: Incoming DIO InstanceID-Version %u-%u\n", (unsigned)dio.instance_id,(unsigned)dio.version);
|
||||||
PRINTF("RPL: Incoming DIO rank %u\n", (unsigned)dio.rank);
|
PRINTF("RPL: Incoming DIO rank %u\n", (unsigned)dio.rank);
|
||||||
|
|
||||||
dio.grounded = buffer[i] & RPL_DIO_GROUNDED;
|
dio.grounded = buffer[i] & RPL_DIO_GROUNDED;
|
||||||
|
@ -224,6 +231,10 @@ dio_input(void)
|
||||||
memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id));
|
memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id));
|
||||||
i += sizeof(dio.dag_id);
|
i += sizeof(dio.dag_id);
|
||||||
|
|
||||||
|
PRINTF("RPL: Incoming DIO DODAG ");
|
||||||
|
PRINT6ADDR(&dio.dag_id);
|
||||||
|
PRINTF(" preference : %u\n",dio.preference);
|
||||||
|
|
||||||
/* Check if there are any DIO suboptions. */
|
/* Check if there are any DIO suboptions. */
|
||||||
for(; i < buffer_length; i += len) {
|
for(; i < buffer_length; i += len) {
|
||||||
subopt_type = buffer[i];
|
subopt_type = buffer[i];
|
||||||
|
@ -249,7 +260,6 @@ dio_input(void)
|
||||||
RPL_STAT(rpl_stats.malformed_msgs++);
|
RPL_STAT(rpl_stats.malformed_msgs++);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dio.mc.type = buffer[i + 2];
|
dio.mc.type = buffer[i + 2];
|
||||||
dio.mc.flags = buffer[i + 3] << 1;
|
dio.mc.flags = buffer[i + 3] << 1;
|
||||||
dio.mc.flags |= buffer[i + 4] >> 7;
|
dio.mc.flags |= buffer[i + 4] >> 7;
|
||||||
|
@ -347,30 +357,50 @@ dio_input(void)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
|
dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr)
|
||||||
{
|
{
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
int pos;
|
int pos;
|
||||||
|
#if !RPL_LEAF_ONLY
|
||||||
uip_ipaddr_t addr;
|
uip_ipaddr_t addr;
|
||||||
|
#endif /* !RPL_LEAF_ONLY */
|
||||||
|
|
||||||
|
#if RPL_LEAF_ONLY
|
||||||
|
/* only respond to unicast DIS */
|
||||||
|
if(uc_addr == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* RPL_LEAF_ONLY */
|
||||||
|
|
||||||
|
rpl_dag_t *dag = instance->current_dag;
|
||||||
|
|
||||||
/* DAG Information Object */
|
/* DAG Information Object */
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
buffer = UIP_ICMP_PAYLOAD;
|
buffer = UIP_ICMP_PAYLOAD;
|
||||||
buffer[pos++] = dag->instance_id;
|
buffer[pos++] = instance->instance_id;
|
||||||
buffer[pos++] = dag->version;
|
buffer[pos++] = dag->version;
|
||||||
|
#if RPL_LEAF_ONLY
|
||||||
|
buffer[pos++] = INFINITE_RANK >> 8;
|
||||||
|
buffer[pos++] = INFINITE_RANK & 0xff;
|
||||||
|
#else /* RPL_LEAF_ONLY */
|
||||||
buffer[pos++] = dag->rank >> 8;
|
buffer[pos++] = dag->rank >> 8;
|
||||||
buffer[pos++] = dag->rank & 0xff;
|
buffer[pos++] = dag->rank & 0xff;
|
||||||
|
#endif /* RPL_LEAF_ONLY */
|
||||||
|
|
||||||
buffer[pos] = 0;
|
buffer[pos] = 0;
|
||||||
if(dag->grounded) {
|
if(dag->grounded) {
|
||||||
buffer[pos] |= RPL_DIO_GROUNDED;
|
buffer[pos] |= RPL_DIO_GROUNDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[pos] = dag->mop << RPL_DIO_MOP_SHIFT;
|
buffer[pos] |= instance->mop << RPL_DIO_MOP_SHIFT;
|
||||||
|
buffer[pos] |= dag->preference & RPL_DIO_PREFERENCE_MASK;
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
buffer[pos++] = ++dag->dtsn_out;
|
buffer[pos++] = instance->dtsn_out;
|
||||||
|
|
||||||
|
if (RPL_LOLLIPOP_IS_INIT(instance->dtsn_out))
|
||||||
|
RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
|
||||||
|
|
||||||
/* reserved 2 bytes */
|
/* reserved 2 bytes */
|
||||||
buffer[pos++] = 0; /* flags */
|
buffer[pos++] = 0; /* flags */
|
||||||
|
@ -379,49 +409,51 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
|
||||||
memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id));
|
memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id));
|
||||||
pos += 16;
|
pos += 16;
|
||||||
|
|
||||||
if(dag->mc.type != RPL_DAG_MC_NONE) {
|
#if !RPL_LEAF_ONLY
|
||||||
dag->of->update_metric_container(dag);
|
if(instance->mc.type != RPL_DAG_MC_NONE) {
|
||||||
|
instance->of->update_metric_container(instance);
|
||||||
|
|
||||||
buffer[pos++] = RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER;
|
buffer[pos++] = RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER;
|
||||||
buffer[pos++] = 6;
|
buffer[pos++] = 6;
|
||||||
buffer[pos++] = dag->mc.type;
|
buffer[pos++] = instance->mc.type;
|
||||||
buffer[pos++] = dag->mc.flags >> 1;
|
buffer[pos++] = instance->mc.flags >> 1;
|
||||||
buffer[pos] = (dag->mc.flags & 1) << 7;
|
buffer[pos] = (instance->mc.flags & 1) << 7;
|
||||||
buffer[pos++] |= (dag->mc.aggr << 4) | dag->mc.prec;
|
buffer[pos++] |= (instance->mc.aggr << 4) | instance->mc.prec;
|
||||||
|
if(instance->mc.type == RPL_DAG_MC_ETX) {
|
||||||
if(dag->mc.type == RPL_DAG_MC_ETX) {
|
|
||||||
buffer[pos++] = 2;
|
buffer[pos++] = 2;
|
||||||
buffer[pos++] = dag->mc.obj.etx >> 8;
|
buffer[pos++] = instance->mc.obj.etx >> 8;
|
||||||
buffer[pos++] = dag->mc.obj.etx & 0xff;
|
buffer[pos++] = instance->mc.obj.etx & 0xff;
|
||||||
} else if(dag->mc.type == RPL_DAG_MC_ENERGY) {
|
} else if(instance->mc.type == RPL_DAG_MC_ENERGY) {
|
||||||
buffer[pos++] = 2;
|
buffer[pos++] = 2;
|
||||||
buffer[pos++] = dag->mc.obj.energy.flags;
|
buffer[pos++] = instance->mc.obj.energy.flags;
|
||||||
buffer[pos++] = dag->mc.obj.energy.energy_est;
|
buffer[pos++] = instance->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)instance->mc.type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always add a sub-option for DAG configuration. */
|
#endif /* RPL_LEAF_ONLY */
|
||||||
|
|
||||||
|
/* Always add a sub-option for DAG configuration */
|
||||||
buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF;
|
buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF;
|
||||||
buffer[pos++] = 14;
|
buffer[pos++] = 14;
|
||||||
buffer[pos++] = 0; /* No Auth, PCS = 0 */
|
buffer[pos++] = 0; /* No Auth, PCS = 0 */
|
||||||
buffer[pos++] = dag->dio_intdoubl;
|
buffer[pos++] = instance->dio_intdoubl;
|
||||||
buffer[pos++] = dag->dio_intmin;
|
buffer[pos++] = instance->dio_intmin;
|
||||||
buffer[pos++] = dag->dio_redundancy;
|
buffer[pos++] = instance->dio_redundancy;
|
||||||
buffer[pos++] = dag->max_rankinc >> 8;
|
buffer[pos++] = instance->max_rankinc >> 8;
|
||||||
buffer[pos++] = dag->max_rankinc & 0xff;
|
buffer[pos++] = instance->max_rankinc & 0xff;
|
||||||
buffer[pos++] = dag->min_hoprankinc >> 8;
|
buffer[pos++] = instance->min_hoprankinc >> 8;
|
||||||
buffer[pos++] = dag->min_hoprankinc & 0xff;
|
buffer[pos++] = instance->min_hoprankinc & 0xff;
|
||||||
/* OCP is in the DAG_CONF option */
|
/* OCP is in the DAG_CONF option */
|
||||||
buffer[pos++] = dag->of->ocp >> 8;
|
buffer[pos++] = instance->of->ocp >> 8;
|
||||||
buffer[pos++] = dag->of->ocp & 0xff;
|
buffer[pos++] = instance->of->ocp & 0xff;
|
||||||
buffer[pos++] = 0; /* reserved */
|
buffer[pos++] = 0; /* reserved */
|
||||||
buffer[pos++] = dag->default_lifetime;
|
buffer[pos++] = instance->default_lifetime;
|
||||||
buffer[pos++] = dag->lifetime_unit >> 8;
|
buffer[pos++] = instance->lifetime_unit >> 8;
|
||||||
buffer[pos++] = dag->lifetime_unit & 0xff;
|
buffer[pos++] = instance->lifetime_unit & 0xff;
|
||||||
|
|
||||||
/* Check if we have a prefix to send also. */
|
/* Check if we have a prefix to send also. */
|
||||||
if(dag->prefix_info.length > 0) {
|
if(dag->prefix_info.length > 0) {
|
||||||
|
@ -445,19 +477,27 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
|
||||||
dag->prefix_info.length);
|
dag->prefix_info.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unicast requests get unicast replies! */
|
#if RPL_LEAF_ONLY
|
||||||
if(uc_addr == NULL) {
|
|
||||||
PRINTF("RPL: Sending a multicast-DIO with rank %u\n",
|
|
||||||
(unsigned)dag->rank);
|
|
||||||
uip_create_linklocal_rplnodes_mcast(&addr);
|
|
||||||
uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
|
||||||
} else {
|
|
||||||
PRINTF("RPL: Sending unicast-DIO with rank %u to ",
|
PRINTF("RPL: Sending unicast-DIO with rank %u to ",
|
||||||
(unsigned)dag->rank);
|
(unsigned)dag->rank);
|
||||||
PRINT6ADDR(uc_addr);
|
PRINT6ADDR(uc_addr);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
||||||
|
#else /* RPL_LEAF_ONLY */
|
||||||
|
/* Unicast requests get unicast replies! */
|
||||||
|
if(uc_addr == NULL) {
|
||||||
|
PRINTF("RPL: Sending a multicast-DIO with rank %u\n",
|
||||||
|
(unsigned)instance->current_dag->rank);
|
||||||
|
uip_create_linklocal_rplnodes_mcast(&addr);
|
||||||
|
uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
||||||
|
} else {
|
||||||
|
PRINTF("RPL: Sending unicast-DIO with rank %u to ",
|
||||||
|
(unsigned)instance->current_dag->rank);
|
||||||
|
PRINT6ADDR(uc_addr);
|
||||||
|
PRINTF("\n");
|
||||||
|
uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
||||||
}
|
}
|
||||||
|
#endif /* RPL_LEAF_ONLY */
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -465,10 +505,11 @@ dao_input(void)
|
||||||
{
|
{
|
||||||
uip_ipaddr_t dao_sender_addr;
|
uip_ipaddr_t dao_sender_addr;
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
|
rpl_instance_t *instance;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
uint16_t sequence;
|
uint16_t sequence;
|
||||||
uint8_t instance_id;
|
uint8_t instance_id;
|
||||||
rpl_lifetime_t lifetime;
|
uint8_t lifetime;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t subopt_type;
|
uint8_t subopt_type;
|
||||||
|
@ -494,32 +535,37 @@ dao_input(void)
|
||||||
|
|
||||||
buffer = UIP_ICMP_PAYLOAD;
|
buffer = UIP_ICMP_PAYLOAD;
|
||||||
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
||||||
|
|
||||||
#if RPL_CONF_ADJUST_LLH_LEN
|
#if RPL_CONF_ADJUST_LLH_LEN
|
||||||
buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */
|
buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
instance_id = buffer[pos++];
|
instance_id = buffer[pos++];
|
||||||
|
|
||||||
dag = rpl_get_dag(instance_id);
|
instance = rpl_get_instance(instance_id);
|
||||||
if(dag == NULL) {
|
if(instance == NULL) {
|
||||||
PRINTF("RPL: Ignoring a DAO for a different RPL instance (%u)\n",
|
PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n",
|
||||||
instance_id);
|
instance_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lifetime = dag->default_lifetime;
|
lifetime = instance->default_lifetime;
|
||||||
|
|
||||||
flags = buffer[pos++];
|
flags = buffer[pos++];
|
||||||
/* reserved */
|
/* reserved */
|
||||||
pos++;
|
pos++;
|
||||||
sequence = buffer[pos++];
|
sequence = buffer[pos++];
|
||||||
|
|
||||||
|
dag = instance->current_dag;
|
||||||
/* Is the DAGID present? */
|
/* Is the DAGID present? */
|
||||||
if(flags & RPL_DAO_D_FLAG) {
|
if(flags & RPL_DAO_D_FLAG) {
|
||||||
/* Currently the DAG ID is ignored since we only use global
|
if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) {
|
||||||
RPL Instance IDs. */
|
PRINTF("RPL: Ignoring a DAO for a DODAG different from ours\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
pos += 16;
|
pos += 16;
|
||||||
|
} else {
|
||||||
|
/* Perhaps, there are verification to do but ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there are any DIO sub-options. */
|
/* Check if there are any DIO sub-options. */
|
||||||
|
@ -529,7 +575,7 @@ dao_input(void)
|
||||||
if(subopt_type == RPL_DIO_SUBOPT_PAD1) {
|
if(subopt_type == RPL_DIO_SUBOPT_PAD1) {
|
||||||
len = 1;
|
len = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Sub-option with a two-byte header and payload */
|
/* Sub-option with a two-byte header + payload */
|
||||||
len = 2 + buffer[i + 1];
|
len = 2 + buffer[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +605,7 @@ dao_input(void)
|
||||||
|
|
||||||
if(lifetime == ZERO_LIFETIME) {
|
if(lifetime == ZERO_LIFETIME) {
|
||||||
/* No-Path DAO received; invoke the route purging routine. */
|
/* No-Path DAO received; invoke the route purging routine. */
|
||||||
if(rep != NULL && rep->state.saved_lifetime == 0) {
|
if(rep != NULL && rep->state.saved_lifetime == 0 && rep->length==prefixlen) {
|
||||||
PRINTF("RPL: Setting expiration timer for prefix ");
|
PRINTF("RPL: Setting expiration timer for prefix ");
|
||||||
PRINT6ADDR(&prefix);
|
PRINT6ADDR(&prefix);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
@ -575,9 +621,11 @@ dao_input(void)
|
||||||
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
||||||
/* Check whether this is a DAO forwarding loop. */
|
/* Check whether this is a DAO forwarding loop. */
|
||||||
p = rpl_find_parent(dag, &dao_sender_addr);
|
p = rpl_find_parent(dag, &dao_sender_addr);
|
||||||
if(p != NULL && DAG_RANK(p->rank, dag) < DAG_RANK(dag->rank, dag)) {
|
/* check if this is a new DAO registration with an "illegal" rank */
|
||||||
|
/* if we already route to this node it is likely */
|
||||||
|
if(p != NULL && DAG_RANK(p->rank, instance) < DAG_RANK(dag->rank, instance)) {
|
||||||
PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
|
PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
|
||||||
DAG_RANK(p->rank, dag), DAG_RANK(dag->rank, dag));
|
DAG_RANK(p->rank, instance), DAG_RANK(dag->rank, instance));
|
||||||
p->rank = INFINITE_RANK;
|
p->rank = INFINITE_RANK;
|
||||||
p->updated = 1;
|
p->updated = 1;
|
||||||
return;
|
return;
|
||||||
|
@ -593,7 +641,7 @@ dao_input(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rep->state.lifetime = RPL_LIFETIME(dag, lifetime);
|
rep->state.lifetime = RPL_LIFETIME(instance, lifetime);
|
||||||
rep->state.learned_from = learned_from;
|
rep->state.learned_from = learned_from;
|
||||||
|
|
||||||
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
||||||
|
@ -603,16 +651,18 @@ dao_input(void)
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
uip_icmp6_send(&dag->preferred_parent->addr,
|
uip_icmp6_send(&dag->preferred_parent->addr,
|
||||||
ICMP6_RPL, RPL_CODE_DAO, buffer_length);
|
ICMP6_RPL, RPL_CODE_DAO, buffer_length);
|
||||||
} else if(flags & RPL_DAO_K_FLAG) {
|
}
|
||||||
dao_ack_output(dag, &dao_sender_addr, sequence);
|
if(flags & RPL_DAO_K_FLAG) {
|
||||||
|
dao_ack_output(instance, &dao_sender_addr, sequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
dao_output(rpl_parent_t *n, uint8_t lifetime)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
|
rpl_instance_t *instance;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
uip_ipaddr_t addr;
|
uip_ipaddr_t addr;
|
||||||
|
@ -626,7 +676,7 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n == NULL) {
|
if(n == NULL) {
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
dag = rpl_get_any_dag();
|
||||||
if(dag == NULL) {
|
if(dag == NULL) {
|
||||||
PRINTF("RPL: Did not join a DAG before sending DAO\n");
|
PRINTF("RPL: Did not join a DAG before sending DAO\n");
|
||||||
return;
|
return;
|
||||||
|
@ -635,19 +685,28 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
||||||
dag = n->dag;
|
dag = n->dag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance = dag->instance;
|
||||||
|
|
||||||
buffer = UIP_ICMP_PAYLOAD;
|
buffer = UIP_ICMP_PAYLOAD;
|
||||||
|
|
||||||
++dao_sequence;
|
RPL_LOLLIPOP_INCREMENT(dao_sequence);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
buffer[pos++] = dag->instance_id;
|
buffer[pos++] = instance->instance_id;
|
||||||
|
buffer[pos] = 0;
|
||||||
|
#if RPL_DAO_SPECIFY_DODAG
|
||||||
|
buffer[pos] |= RPL_DAO_D_FLAG;
|
||||||
|
#endif /* RPL_DAO_SPECIFY_DODAG */
|
||||||
#if RPL_CONF_DAO_ACK
|
#if RPL_CONF_DAO_ACK
|
||||||
buffer[pos++] = RPL_DAO_K_FLAG; /* DAO ACK request, no DODAGID */
|
buffer[pos] |= RPL_DAO_K_FLAG;
|
||||||
#else
|
#endif /* RPL_CONF_DAO_ACK */
|
||||||
buffer[pos++] = 0; /* No DAO ACK request, no DODAGID */
|
++pos;
|
||||||
#endif
|
|
||||||
buffer[pos++] = 0; /* reserved */
|
buffer[pos++] = 0; /* reserved */
|
||||||
buffer[pos++] = dao_sequence & 0xff;
|
buffer[pos++] = dao_sequence;
|
||||||
|
#if RPL_DAO_SPECIFY_DODAG
|
||||||
|
memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id));
|
||||||
|
pos+=sizeof(dag->dag_id);
|
||||||
|
#endif /* RPL_DAO_SPECIFY_DODAG */
|
||||||
|
|
||||||
/* create target subopt */
|
/* create target subopt */
|
||||||
prefixlen = sizeof(prefix) * CHAR_BIT;
|
prefixlen = sizeof(prefix) * CHAR_BIT;
|
||||||
|
@ -696,9 +755,6 @@ dao_ack_input(void)
|
||||||
|
|
||||||
buffer = UIP_ICMP_PAYLOAD;
|
buffer = UIP_ICMP_PAYLOAD;
|
||||||
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
|
||||||
#if RPL_CONF_ADJUST_LLH_LEN
|
|
||||||
buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header
|
|
||||||
#endif
|
|
||||||
|
|
||||||
instance_id = buffer[0];
|
instance_id = buffer[0];
|
||||||
sequence = buffer[2];
|
sequence = buffer[2];
|
||||||
|
@ -711,7 +767,7 @@ dao_ack_input(void)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence)
|
dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence)
|
||||||
{
|
{
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
|
||||||
|
@ -721,7 +777,7 @@ dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence)
|
||||||
|
|
||||||
buffer = UIP_ICMP_PAYLOAD;
|
buffer = UIP_ICMP_PAYLOAD;
|
||||||
|
|
||||||
buffer[0] = dag->instance_id;
|
buffer[0] = instance->instance_id;
|
||||||
buffer[1] = 0;
|
buffer[1] = 0;
|
||||||
buffer[2] = sequence;
|
buffer[2] = sequence;
|
||||||
buffer[3] = 0;
|
buffer[3] = 0;
|
||||||
|
|
|
@ -46,19 +46,21 @@
|
||||||
#include "net/rpl/rpl-private.h"
|
#include "net/rpl/rpl-private.h"
|
||||||
#include "net/neighbor-info.h"
|
#include "net/neighbor-info.h"
|
||||||
|
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG 1
|
||||||
#include "net/uip-debug.h"
|
#include "net/uip-debug.h"
|
||||||
|
|
||||||
static void reset(rpl_dag_t *);
|
static void reset(rpl_dag_t *);
|
||||||
static void parent_state_callback(rpl_parent_t *, int, int);
|
static void parent_state_callback(rpl_parent_t *, int, int);
|
||||||
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
||||||
|
static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *);
|
||||||
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
||||||
static void update_metric_container(rpl_dag_t *);
|
static void update_metric_container(rpl_instance_t *);
|
||||||
|
|
||||||
rpl_of_t rpl_of_etx = {
|
rpl_of_t rpl_of_etx = {
|
||||||
reset,
|
reset,
|
||||||
parent_state_callback,
|
parent_state_callback,
|
||||||
best_parent,
|
best_parent,
|
||||||
|
best_dag,
|
||||||
calculate_rank,
|
calculate_rank,
|
||||||
update_metric_container,
|
update_metric_container,
|
||||||
1
|
1
|
||||||
|
@ -86,14 +88,14 @@ typedef uint16_t rpl_path_metric_t;
|
||||||
static rpl_path_metric_t
|
static rpl_path_metric_t
|
||||||
calculate_path_metric(rpl_parent_t *p)
|
calculate_path_metric(rpl_parent_t *p)
|
||||||
{
|
{
|
||||||
if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag))) {
|
if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag->instance))) {
|
||||||
return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
|
return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
|
||||||
}
|
}
|
||||||
return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric);
|
return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reset(rpl_dag_t *dag)
|
reset(rpl_dag_t *sag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
||||||
}
|
}
|
||||||
rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC;
|
rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC;
|
||||||
} else {
|
} else {
|
||||||
rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc;
|
rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->instance->min_hoprankinc;
|
||||||
if(base_rank == 0) {
|
if(base_rank == 0) {
|
||||||
base_rank = p->rank;
|
base_rank = p->rank;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +134,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
||||||
return new_rank;
|
return new_rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rpl_dag_t *
|
||||||
|
best_dag(rpl_dag_t *d1, rpl_dag_t *d2)
|
||||||
|
{
|
||||||
|
if(d1->grounded) {
|
||||||
|
if (!d2->grounded) {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
} else if(d2->grounded) {
|
||||||
|
return d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d1->preference < d2->preference) {
|
||||||
|
return d2;
|
||||||
|
} else {
|
||||||
|
if(d1->preference > d2->preference) {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d2->rank < d1->rank) {
|
||||||
|
return d2;
|
||||||
|
} else {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static rpl_parent_t *
|
static rpl_parent_t *
|
||||||
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||||
{
|
{
|
||||||
|
@ -164,18 +192,26 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_metric_container(rpl_dag_t *dag)
|
update_metric_container(rpl_instance_t *instance)
|
||||||
{
|
{
|
||||||
rpl_path_metric_t path_metric;
|
rpl_path_metric_t path_metric;
|
||||||
|
rpl_dag_t *dag;
|
||||||
#if RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
#if RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dag->mc.flags = RPL_DAG_MC_FLAG_P;
|
instance->mc.flags = RPL_DAG_MC_FLAG_P;
|
||||||
dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
||||||
dag->mc.prec = 0;
|
instance->mc.prec = 0;
|
||||||
|
|
||||||
if(dag->rank == ROOT_RANK(dag)) {
|
dag = instance->current_dag;
|
||||||
|
|
||||||
|
if (!dag->joined) {
|
||||||
|
/* We should probably do something here */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dag->rank == ROOT_RANK(instance)) {
|
||||||
path_metric = 0;
|
path_metric = 0;
|
||||||
} else {
|
} else {
|
||||||
path_metric = calculate_path_metric(dag->preferred_parent);
|
path_metric = calculate_path_metric(dag->preferred_parent);
|
||||||
|
@ -183,27 +219,27 @@ update_metric_container(rpl_dag_t *dag)
|
||||||
|
|
||||||
#if RPL_DAG_MC == RPL_DAG_MC_ETX
|
#if RPL_DAG_MC == RPL_DAG_MC_ETX
|
||||||
|
|
||||||
dag->mc.type = RPL_DAG_MC_ETX;
|
instance->mc.type = RPL_DAG_MC_ETX;
|
||||||
dag->mc.length = sizeof(dag->mc.obj.etx);
|
instance->mc.length = sizeof(instance->mc.obj.etx);
|
||||||
dag->mc.obj.etx = path_metric;
|
instance->mc.obj.etx = path_metric;
|
||||||
|
|
||||||
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.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
|
instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
|
||||||
(dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);
|
(instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);
|
||||||
|
|
||||||
#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
||||||
|
|
||||||
dag->mc.type = RPL_DAG_MC_ENERGY;
|
instance->mc.type = RPL_DAG_MC_ENERGY;
|
||||||
dag->mc.length = sizeof(dag->mc.obj.energy);
|
instance->mc.length = sizeof(instance->mc.obj.energy);
|
||||||
|
|
||||||
if(dag->rank == ROOT_RANK(dag)) {
|
if(dag->rank == ROOT_RANK(instance)) {
|
||||||
type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
|
type = RPL_DAG_MC_ENERGY_TYPE_MAINS;
|
||||||
} else {
|
} else {
|
||||||
type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
|
type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
dag->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
|
instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
|
||||||
dag->mc.obj.energy.energy_est = path_metric;
|
instance->mc.obj.energy.energy_est = path_metric;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
|
|
||||||
static void reset(rpl_dag_t *);
|
static void reset(rpl_dag_t *);
|
||||||
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
||||||
|
static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *);
|
||||||
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
|
||||||
static void update_metric_container(rpl_dag_t *);
|
static void update_metric_container(rpl_dag_t *);
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ rpl_of_t rpl_of0 = {
|
||||||
reset,
|
reset,
|
||||||
NULL,
|
NULL,
|
||||||
best_parent,
|
best_parent,
|
||||||
|
best_dag,
|
||||||
calculate_rank,
|
calculate_rank,
|
||||||
update_metric_container,
|
update_metric_container,
|
||||||
0
|
0
|
||||||
|
@ -92,6 +94,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rpl_dag_t *
|
||||||
|
best_dag(rpl_dag_t *d1, rpl_dag_t *d2)
|
||||||
|
{
|
||||||
|
if(d1->grounded) {
|
||||||
|
if (!d2->grounded) {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
} else if(d2->grounded) {
|
||||||
|
return d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d1->preference < d2->preference) {
|
||||||
|
return d2;
|
||||||
|
} else {
|
||||||
|
if(d1->preference > d2->preference) {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d2->rank < d1->rank) {
|
||||||
|
return d2;
|
||||||
|
} else {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static rpl_parent_t *
|
static rpl_parent_t *
|
||||||
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||||
{
|
{
|
||||||
|
@ -127,7 +155,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_metric_container(rpl_dag_t *dag)
|
update_metric_container(rpl_instance_t *instance)
|
||||||
{
|
{
|
||||||
dag->mc.type = RPL_DAG_MC_NONE;
|
instance->mc.type = RPL_DAG_MC_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,8 @@
|
||||||
/* Default route lifetime as a multiple of the lifetime unit. */
|
/* Default route lifetime as a multiple of the lifetime unit. */
|
||||||
#define RPL_DEFAULT_LIFETIME 0xff
|
#define RPL_DEFAULT_LIFETIME 0xff
|
||||||
|
|
||||||
#define RPL_LIFETIME(dag, lifetime) \
|
#define RPL_LIFETIME(instance, lifetime) \
|
||||||
((unsigned long)(dag)->lifetime_unit * lifetime)
|
(((unsigned long)(instance)->lifetime_unit) * lifetime)
|
||||||
|
|
||||||
#ifndef RPL_CONF_MIN_HOPRANKINC
|
#ifndef RPL_CONF_MIN_HOPRANKINC
|
||||||
#define DEFAULT_MIN_HOPRANKINC 256
|
#define DEFAULT_MIN_HOPRANKINC 256
|
||||||
|
@ -117,13 +117,13 @@
|
||||||
#endif
|
#endif
|
||||||
#define DEFAULT_MAX_RANKINC (3 * DEFAULT_MIN_HOPRANKINC)
|
#define DEFAULT_MAX_RANKINC (3 * DEFAULT_MIN_HOPRANKINC)
|
||||||
|
|
||||||
#define DAG_RANK(fixpt_rank, dag) ((fixpt_rank) / (dag)->min_hoprankinc)
|
#define DAG_RANK(fixpt_rank, instance) ((fixpt_rank) / (instance)->min_hoprankinc)
|
||||||
|
|
||||||
/* Rank of a virtual root node that coordinates DAG root nodes. */
|
/* Rank of a virtual root node that coordinates DAG root nodes. */
|
||||||
#define BASE_RANK 0
|
#define BASE_RANK 0
|
||||||
|
|
||||||
/* Rank of a root node. */
|
/* Rank of a root node. */
|
||||||
#define ROOT_RANK(dag) (dag)->min_hoprankinc
|
#define ROOT_RANK(instance) (instance)->min_hoprankinc
|
||||||
|
|
||||||
#define INFINITE_RANK 0xffff
|
#define INFINITE_RANK 0xffff
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ struct rpl_dio {
|
||||||
uint8_t dag_intdoubl;
|
uint8_t dag_intdoubl;
|
||||||
uint8_t dag_intmin;
|
uint8_t dag_intmin;
|
||||||
uint8_t dag_redund;
|
uint8_t dag_redund;
|
||||||
rpl_lifetime_t default_lifetime;
|
uint8_t default_lifetime;
|
||||||
uint16_t lifetime_unit;
|
uint16_t lifetime_unit;
|
||||||
rpl_rank_t dag_max_rankinc;
|
rpl_rank_t dag_max_rankinc;
|
||||||
rpl_rank_t dag_min_hoprankinc;
|
rpl_rank_t dag_min_hoprankinc;
|
||||||
|
@ -240,33 +240,50 @@ extern rpl_stats_t rpl_stats;
|
||||||
#define RPL_STAT(code)
|
#define RPL_STAT(code)
|
||||||
#endif /* RPL_CONF_STATS */
|
#endif /* RPL_CONF_STATS */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Instances */
|
||||||
|
extern rpl_instance_t instance_table[];
|
||||||
|
rpl_instance_t *default_instance;
|
||||||
|
|
||||||
/* ICMPv6 functions for RPL. */
|
/* ICMPv6 functions for RPL. */
|
||||||
void dis_output(uip_ipaddr_t *addr);
|
void dis_output(uip_ipaddr_t *addr);
|
||||||
void dio_output(rpl_dag_t *, uip_ipaddr_t *uc_addr);
|
void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr);
|
||||||
void dao_output(rpl_parent_t *, rpl_lifetime_t lifetime);
|
void dao_output(rpl_parent_t *, uint8_t lifetime);
|
||||||
void dao_ack_output(rpl_dag_t *, uip_ipaddr_t *, uint8_t);
|
void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t);
|
||||||
void uip_rpl_input(void);
|
void uip_rpl_input(void);
|
||||||
|
|
||||||
|
/* RPL Header Option */
|
||||||
|
int rpl_verify_header(int uip_ext_opt_offset);
|
||||||
|
void rpl_update_header_empty();
|
||||||
|
int rpl_update_header_final(uip_ipaddr_t *addr);
|
||||||
|
|
||||||
/* RPL logic functions. */
|
/* RPL logic functions. */
|
||||||
void rpl_join_dag(rpl_dag_t *);
|
void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio);
|
||||||
void rpl_local_repair(rpl_dag_t *dag);
|
void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio);
|
||||||
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from);
|
void rpl_local_repair(rpl_instance_t *instance);
|
||||||
void rpl_process_dio(uip_ipaddr_t *, rpl_dio_t *);
|
void rpl_process_dio(uip_ipaddr_t *, rpl_dio_t *);
|
||||||
int rpl_process_parent_event(rpl_dag_t *, rpl_parent_t *);
|
int rpl_process_parent_event(rpl_instance_t *, rpl_parent_t *);
|
||||||
|
|
||||||
/* DAG object management. */
|
/* DAG object management. */
|
||||||
rpl_dag_t *rpl_alloc_dag(uint8_t);
|
rpl_dag_t *rpl_alloc_dodag(uint8_t, uip_ipaddr_t *);
|
||||||
void rpl_free_dag(rpl_dag_t *);
|
rpl_instance_t *rpl_alloc_instance(uint8_t);
|
||||||
|
void rpl_free_dodag(rpl_dag_t *);
|
||||||
|
void rpl_free_instance(rpl_instance_t *);
|
||||||
|
|
||||||
/* DAG parent management function. */
|
/* DAG parent management function. */
|
||||||
rpl_parent_t *rpl_add_parent(rpl_dag_t *, rpl_dio_t *dio, uip_ipaddr_t *);
|
rpl_parent_t *rpl_add_parent(rpl_dag_t *, rpl_dio_t *dio, uip_ipaddr_t *);
|
||||||
rpl_parent_t *rpl_find_parent(rpl_dag_t *, uip_ipaddr_t *);
|
rpl_parent_t *rpl_find_parent(rpl_dag_t *, uip_ipaddr_t *);
|
||||||
int rpl_remove_parent(rpl_dag_t *, rpl_parent_t *);
|
rpl_parent_t * rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr);
|
||||||
|
rpl_dag_t * rpl_find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr);
|
||||||
|
void rpl_nullify_parent(rpl_dag_t *, rpl_parent_t *);
|
||||||
|
void rpl_remove_parent(rpl_dag_t *, rpl_parent_t *);
|
||||||
|
void rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent);
|
||||||
rpl_parent_t *rpl_select_parent(rpl_dag_t *dag);
|
rpl_parent_t *rpl_select_parent(rpl_dag_t *dag);
|
||||||
|
rpl_dag_t *rpl_select_dodag(rpl_instance_t *instance,rpl_parent_t *parent);
|
||||||
void rpl_recalculate_ranks(void);
|
void rpl_recalculate_ranks(void);
|
||||||
|
|
||||||
/* RPL routing table functions. */
|
/* RPL routing table functions. */
|
||||||
void rpl_remove_routes(rpl_dag_t *dag);
|
void rpl_remove_routes(rpl_dag_t *dag);
|
||||||
|
void rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag);
|
||||||
uip_ds6_route_t *rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix,
|
uip_ds6_route_t *rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix,
|
||||||
int prefix_len, uip_ipaddr_t *next_hop);
|
int prefix_len, uip_ipaddr_t *next_hop);
|
||||||
void rpl_purge_routes(void);
|
void rpl_purge_routes(void);
|
||||||
|
@ -275,8 +292,8 @@ void rpl_purge_routes(void);
|
||||||
rpl_of_t *rpl_find_of(rpl_ocp_t);
|
rpl_of_t *rpl_find_of(rpl_ocp_t);
|
||||||
|
|
||||||
/* Timer functions. */
|
/* Timer functions. */
|
||||||
void rpl_schedule_dao(rpl_dag_t *);
|
void rpl_schedule_dao(rpl_instance_t *);
|
||||||
void rpl_reset_dio_timer(rpl_dag_t *, uint8_t);
|
void rpl_reset_dio_timer(rpl_instance_t *, uint8_t);
|
||||||
void rpl_reset_periodic_timer(void);
|
void rpl_reset_periodic_timer(void);
|
||||||
|
|
||||||
/* Route poisoning. */
|
/* Route poisoning. */
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
static struct ctimer periodic_timer;
|
static struct ctimer periodic_timer;
|
||||||
|
|
||||||
static void handle_periodic_timer(void *ptr);
|
static void handle_periodic_timer(void *ptr);
|
||||||
static void new_dio_interval(rpl_dag_t *dag);
|
static void new_dio_interval(rpl_instance_t *instance);
|
||||||
static void handle_dio_timer(void *ptr);
|
static void handle_dio_timer(void *ptr);
|
||||||
|
|
||||||
static uint16_t next_dis;
|
static uint16_t next_dis;
|
||||||
|
@ -69,7 +69,7 @@ handle_periodic_timer(void *ptr)
|
||||||
/* handle DIS */
|
/* handle DIS */
|
||||||
#ifdef RPL_DIS_SEND
|
#ifdef RPL_DIS_SEND
|
||||||
next_dis++;
|
next_dis++;
|
||||||
if(rpl_get_dag(RPL_ANY_INSTANCE) == NULL && next_dis >= RPL_DIS_INTERVAL) {
|
if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) {
|
||||||
next_dis = 0;
|
next_dis = 0;
|
||||||
dis_output(NULL);
|
dis_output(NULL);
|
||||||
}
|
}
|
||||||
|
@ -78,17 +78,17 @@ handle_periodic_timer(void *ptr)
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
static void
|
static void
|
||||||
new_dio_interval(rpl_dag_t *dag)
|
new_dio_interval(rpl_instance_t *instance)
|
||||||
{
|
{
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
|
|
||||||
/* TODO: too small timer intervals for many cases */
|
/* TODO: too small timer intervals for many cases */
|
||||||
time = 1UL << dag->dio_intcurrent;
|
time = 1UL << instance->dio_intcurrent;
|
||||||
|
|
||||||
/* Convert from milliseconds to CLOCK_TICKS. */
|
/* Convert from milliseconds to CLOCK_TICKS. */
|
||||||
time = (time * CLOCK_SECOND) / 1000;
|
time = (time * CLOCK_SECOND) / 1000;
|
||||||
|
|
||||||
dag->dio_next_delay = time;
|
instance->dio_next_delay = time;
|
||||||
|
|
||||||
/* random number between I/2 and I */
|
/* random number between I/2 and I */
|
||||||
time = time >> 1;
|
time = time >> 1;
|
||||||
|
@ -99,36 +99,36 @@ new_dio_interval(rpl_dag_t *dag)
|
||||||
* operate efficiently. Therefore we need to calculate the delay between
|
* operate efficiently. Therefore we need to calculate the delay between
|
||||||
* the randomized time and the start time of the next interval.
|
* the randomized time and the start time of the next interval.
|
||||||
*/
|
*/
|
||||||
dag->dio_next_delay -= time;
|
instance->dio_next_delay -= time;
|
||||||
dag->dio_send = 1;
|
instance->dio_send = 1;
|
||||||
|
|
||||||
#if RPL_CONF_STATS
|
#if RPL_CONF_STATS
|
||||||
/* keep some stats */
|
/* keep some stats */
|
||||||
dag->dio_totint++;
|
instance->dio_totint++;
|
||||||
dag->dio_totrecv += dag->dio_counter;
|
instance->dio_totrecv += instance->dio_counter;
|
||||||
ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n",
|
ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n",
|
||||||
DAG_RANK(dag->rank, dag),
|
DAG_RANK(instance->current_dag->rank, instance),
|
||||||
(10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc,
|
(10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc,
|
||||||
dag->version,
|
instance->current_dag->version,
|
||||||
dag->dio_totint, dag->dio_totsend,
|
instance->dio_totint, instance->dio_totsend,
|
||||||
dag->dio_totrecv,dag->dio_intcurrent,
|
instance->dio_totrecv,instance->dio_intcurrent,
|
||||||
dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE");
|
instance->current_dag->rank == ROOT_RANK(instance) ? "BLUE" : "ORANGE");
|
||||||
#endif /* RPL_CONF_STATS */
|
#endif /* RPL_CONF_STATS */
|
||||||
|
|
||||||
/* reset the redundancy counter */
|
/* reset the redundancy counter */
|
||||||
dag->dio_counter = 0;
|
instance->dio_counter = 0;
|
||||||
|
|
||||||
/* schedule the timer */
|
/* schedule the timer */
|
||||||
PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", time);
|
PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", time);
|
||||||
ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag);
|
ctimer_set(&instance->dio_timer, time, &handle_dio_timer, instance);
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
static void
|
static void
|
||||||
handle_dio_timer(void *ptr)
|
handle_dio_timer(void *ptr)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_instance_t *instance;
|
||||||
|
|
||||||
dag = (rpl_dag_t *)ptr;
|
instance = (rpl_instance_t *)ptr;
|
||||||
|
|
||||||
PRINTF("RPL: DIO Timer triggered\n");
|
PRINTF("RPL: DIO Timer triggered\n");
|
||||||
if(!dio_send_ok) {
|
if(!dio_send_ok) {
|
||||||
|
@ -136,33 +136,33 @@ handle_dio_timer(void *ptr)
|
||||||
dio_send_ok = 1;
|
dio_send_ok = 1;
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RPL: Postponing DIO transmission since link local address is not ok\n");
|
PRINTF("RPL: Postponing DIO transmission since link local address is not ok\n");
|
||||||
ctimer_set(&dag->dio_timer, CLOCK_SECOND, &handle_dio_timer, dag);
|
ctimer_set(&instance->dio_timer, CLOCK_SECOND, &handle_dio_timer, instance);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dag->dio_send) {
|
if(instance->dio_send) {
|
||||||
/* send DIO if counter is less than desired redundancy */
|
/* send DIO if counter is less than desired redundancy */
|
||||||
if(dag->dio_counter < dag->dio_redundancy) {
|
if(instance->dio_counter < instance->dio_redundancy) {
|
||||||
#if RPL_CONF_STATS
|
#if RPL_CONF_STATS
|
||||||
dag->dio_totsend++;
|
instance->dio_totsend++;
|
||||||
#endif /* RPL_CONF_STATS */
|
#endif /* RPL_CONF_STATS */
|
||||||
dio_output(dag, NULL);
|
dio_output(instance, NULL);
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n",
|
PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n",
|
||||||
dag->dio_counter, dag->dio_redundancy);
|
instance->dio_counter, instance->dio_redundancy);
|
||||||
}
|
}
|
||||||
dag->dio_send = 0;
|
instance->dio_send = 0;
|
||||||
PRINTF("RPL: Scheduling DIO timer %u ticks in future (sent)\n",
|
PRINTF("RPL: Scheduling DIO timer %"PRIu32" ticks in future (sent)\n",
|
||||||
dag->dio_next_delay);
|
instance->dio_next_delay);
|
||||||
ctimer_set(&dag->dio_timer, dag->dio_next_delay, handle_dio_timer, dag);
|
ctimer_set(&instance->dio_timer, instance->dio_next_delay, handle_dio_timer, instance);
|
||||||
} else {
|
} else {
|
||||||
/* check if we need to double interval */
|
/* check if we need to double interval */
|
||||||
if(dag->dio_intcurrent < dag->dio_intmin + dag->dio_intdoubl) {
|
if(instance->dio_intcurrent < instance->dio_intmin + instance->dio_intdoubl) {
|
||||||
dag->dio_intcurrent++;
|
instance->dio_intcurrent++;
|
||||||
PRINTF("RPL: DIO Timer interval doubled %d\n", dag->dio_intcurrent);
|
PRINTF("RPL: DIO Timer interval doubled %d\n", instance->dio_intcurrent);
|
||||||
}
|
}
|
||||||
new_dio_interval(dag);
|
new_dio_interval(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -173,61 +173,63 @@ rpl_reset_periodic_timer(void)
|
||||||
ctimer_set(&periodic_timer, CLOCK_SECOND, handle_periodic_timer, NULL);
|
ctimer_set(&periodic_timer, CLOCK_SECOND, handle_periodic_timer, NULL);
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Resets the DIO timer in the DAG to its minimal interval. */
|
/* Resets the DIO timer in the instance to its minimal interval. */
|
||||||
void
|
void
|
||||||
rpl_reset_dio_timer(rpl_dag_t *dag, uint8_t force)
|
rpl_reset_dio_timer(rpl_instance_t *instance, uint8_t force)
|
||||||
{
|
{
|
||||||
|
#if !RPL_LEAF_ONLY
|
||||||
/* only reset if not just reset or started */
|
/* only reset if not just reset or started */
|
||||||
if(force || dag->dio_intcurrent > dag->dio_intmin) {
|
if(force || instance->dio_intcurrent > instance->dio_intmin) {
|
||||||
dag->dio_counter = 0;
|
instance->dio_counter = 0;
|
||||||
dag->dio_intcurrent = dag->dio_intmin;
|
instance->dio_intcurrent = instance->dio_intmin;
|
||||||
new_dio_interval(dag);
|
new_dio_interval(instance);
|
||||||
}
|
}
|
||||||
#if RPL_CONF_STATS
|
#if RPL_CONF_STATS
|
||||||
rpl_stats.resets++;
|
rpl_stats.resets++;
|
||||||
#endif
|
#endif /* RPL_CONF_STATS */
|
||||||
|
#endif /* RPL_LEAF_ONLY */
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
static void
|
static void
|
||||||
handle_dao_timer(void *ptr)
|
handle_dao_timer(void *ptr)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_instance_t *instance;
|
||||||
|
|
||||||
dag = (rpl_dag_t *)ptr;
|
instance = (rpl_instance_t *)ptr;
|
||||||
|
|
||||||
if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
|
if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
|
||||||
PRINTF("RPL: Postpone DAO transmission... \n");
|
PRINTF("RPL: Postpone DAO transmission... \n");
|
||||||
ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag);
|
ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the DAO to the DAO parent set -- the preferred parent in our case. */
|
/* Send the DAO to the DAO parent set -- the preferred parent in our case. */
|
||||||
if(dag->preferred_parent != NULL) {
|
if(instance->current_dag->preferred_parent != NULL) {
|
||||||
PRINTF("RPL: handle_dao_timer - sending DAO\n");
|
PRINTF("RPL: handle_dao_timer - sending DAO\n");
|
||||||
/* Set the route lifetime to the default value. */
|
/* Set the route lifetime to the default value. */
|
||||||
dao_output(dag->preferred_parent, dag->default_lifetime);
|
dao_output(instance->current_dag->preferred_parent, instance->default_lifetime);
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RPL: No suitable DAO parent\n");
|
PRINTF("RPL: No suitable DAO parent\n");
|
||||||
}
|
}
|
||||||
ctimer_stop(&dag->dao_timer);
|
ctimer_stop(&instance->dao_timer);
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
void
|
void
|
||||||
rpl_schedule_dao(rpl_dag_t *dag)
|
rpl_schedule_dao(rpl_instance_t *instance)
|
||||||
{
|
{
|
||||||
clock_time_t expiration_time;
|
clock_time_t expiration_time;
|
||||||
|
|
||||||
expiration_time = etimer_expiration_time(&dag->dao_timer.etimer);
|
expiration_time = etimer_expiration_time(&instance->dao_timer.etimer);
|
||||||
|
|
||||||
if(!etimer_expired(&dag->dao_timer.etimer)) {
|
if(!etimer_expired(&instance->dao_timer.etimer)) {
|
||||||
PRINTF("RPL: DAO timer already scheduled\n");
|
PRINTF("RPL: DAO timer already scheduled\n");
|
||||||
} else {
|
} else {
|
||||||
expiration_time = DEFAULT_DAO_LATENCY / 2 +
|
expiration_time = DEFAULT_DAO_LATENCY / 2 +
|
||||||
(random_rand() % (DEFAULT_DAO_LATENCY));
|
(random_rand() % (DEFAULT_DAO_LATENCY));
|
||||||
PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n",
|
PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n",
|
||||||
(unsigned)expiration_time);
|
(unsigned)expiration_time);
|
||||||
ctimer_set(&dag->dao_timer, expiration_time,
|
ctimer_set(&instance->dao_timer, expiration_time,
|
||||||
handle_dao_timer, dag);
|
handle_dao_timer, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
@ -57,6 +57,15 @@ rpl_stats_t rpl_stats;
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
|
extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
|
||||||
|
|
||||||
|
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||||
|
#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
|
||||||
|
#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
|
||||||
|
#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN])
|
||||||
|
#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
|
||||||
|
#define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
|
||||||
|
#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
void
|
void
|
||||||
rpl_purge_routes(void)
|
rpl_purge_routes(void)
|
||||||
|
@ -86,6 +95,23 @@ rpl_remove_routes(rpl_dag_t *dag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
void
|
||||||
|
rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag)
|
||||||
|
{
|
||||||
|
uip_ds6_route_t *locroute;
|
||||||
|
|
||||||
|
for(locroute = uip_ds6_routing_table;
|
||||||
|
locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB;
|
||||||
|
locroute++) {
|
||||||
|
if(locroute->isused
|
||||||
|
&& uip_ipaddr_cmp(&locroute->nexthop, nexthop)
|
||||||
|
&& locroute->state.dag == dag) {
|
||||||
|
locroute->isused = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
uip_ds6_route_t *
|
uip_ds6_route_t *
|
||||||
rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
|
rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
|
||||||
uip_ipaddr_t *next_hop)
|
uip_ipaddr_t *next_hop)
|
||||||
|
@ -107,7 +133,7 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
|
||||||
uip_ipaddr_copy(&rep->nexthop, next_hop);
|
uip_ipaddr_copy(&rep->nexthop, next_hop);
|
||||||
}
|
}
|
||||||
rep->state.dag = dag;
|
rep->state.dag = dag;
|
||||||
rep->state.lifetime = RPL_LIFETIME(dag, dag->default_lifetime);
|
rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime);
|
||||||
rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL;
|
rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL;
|
||||||
|
|
||||||
PRINTF("RPL: Added a route to ");
|
PRINTF("RPL: Added a route to ");
|
||||||
|
@ -123,8 +149,9 @@ static void
|
||||||
rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
|
rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
|
||||||
{
|
{
|
||||||
uip_ipaddr_t ipaddr;
|
uip_ipaddr_t ipaddr;
|
||||||
rpl_dag_t *dag;
|
|
||||||
rpl_parent_t *parent;
|
rpl_parent_t *parent;
|
||||||
|
rpl_instance_t *instance;
|
||||||
|
rpl_instance_t *end;
|
||||||
|
|
||||||
uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
||||||
uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
|
uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
|
||||||
|
@ -132,68 +159,57 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
|
||||||
PRINT6ADDR(&ipaddr);
|
PRINT6ADDR(&ipaddr);
|
||||||
PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
|
PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
|
||||||
|
|
||||||
dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
|
for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||||
if(dag == NULL) {
|
if ( instance->used == 1 ) {
|
||||||
return;
|
parent = rpl_find_parent_any_dag(instance, &ipaddr);
|
||||||
|
if(!(parent == NULL)) {
|
||||||
|
/* Trigger DAG rank recalculation. */
|
||||||
|
parent->updated = 1;
|
||||||
|
parent->link_metric = etx;
|
||||||
|
|
||||||
|
if(instance->of->parent_state_callback != NULL) {
|
||||||
|
instance->of->parent_state_callback(parent, known, etx);
|
||||||
|
}
|
||||||
|
if(!known) {
|
||||||
|
PRINTF("RPL: Removing parent ");
|
||||||
|
PRINT6ADDR(&parent->addr);
|
||||||
|
PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx);
|
||||||
|
parent->rank = INFINITE_RANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = rpl_find_parent(dag, &ipaddr);
|
if (!known) {
|
||||||
if(parent == NULL) {
|
|
||||||
if(!known) {
|
|
||||||
PRINTF("RPL: Deleting routes installed by DAOs received from ");
|
PRINTF("RPL: Deleting routes installed by DAOs received from ");
|
||||||
PRINT6ADDR(&ipaddr);
|
PRINT6ADDR(&ipaddr);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
uip_ds6_route_rm_by_nexthop(&ipaddr);
|
uip_ds6_route_rm_by_nexthop(&ipaddr);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trigger DAG rank recalculation. */
|
|
||||||
parent->updated = 1;
|
|
||||||
|
|
||||||
parent->link_metric = etx;
|
|
||||||
|
|
||||||
if(dag->of->parent_state_callback != NULL) {
|
|
||||||
dag->of->parent_state_callback(parent, known, etx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!known) {
|
|
||||||
PRINTF("RPL: Removing parent ");
|
|
||||||
PRINT6ADDR(&parent->addr);
|
|
||||||
PRINTF(" because of bad connectivity (ETX %d)\n", etx);
|
|
||||||
parent->rank = INFINITE_RANK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
void
|
void
|
||||||
rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p;
|
||||||
|
rpl_instance_t *instance;
|
||||||
/* This only handles one DODAG - if multiple we need to check all */
|
rpl_instance_t *end;
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
|
||||||
if(dag == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if this is our default route then clean the dag->def_route state */
|
|
||||||
if(dag->def_route != NULL &&
|
|
||||||
uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) {
|
|
||||||
dag->def_route = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!nbr->isused) {
|
if(!nbr->isused) {
|
||||||
PRINTF("RPL: Removing neighbor ");
|
PRINTF("RPL: Removing neighbor ");
|
||||||
PRINT6ADDR(&nbr->ipaddr);
|
PRINT6ADDR(&nbr->ipaddr);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
p = rpl_find_parent(dag, &nbr->ipaddr);
|
for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||||
|
if ( instance->used == 1 ) {
|
||||||
|
p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
|
||||||
if(p != NULL) {
|
if(p != NULL) {
|
||||||
p->rank = INFINITE_RANK;
|
p->rank = INFINITE_RANK;
|
||||||
/* Trigger DAG rank recalculation. */
|
/* Trigger DAG rank recalculation. */
|
||||||
p->updated = 1;
|
p->updated = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
void
|
void
|
||||||
|
@ -201,6 +217,7 @@ rpl_init(void)
|
||||||
{
|
{
|
||||||
uip_ipaddr_t rplmaddr;
|
uip_ipaddr_t rplmaddr;
|
||||||
PRINTF("RPL started\n");
|
PRINTF("RPL started\n");
|
||||||
|
default_instance=NULL;
|
||||||
|
|
||||||
rpl_reset_periodic_timer();
|
rpl_reset_periodic_timer();
|
||||||
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
||||||
|
@ -214,3 +231,299 @@ rpl_init(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
int
|
||||||
|
rpl_verify_header(int uip_ext_opt_offset)
|
||||||
|
{
|
||||||
|
rpl_instance_t *instance;
|
||||||
|
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
|
||||||
|
PRINTF("RPL: Bad header option (wrong length) !\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_FWD_ERR) {
|
||||||
|
PRINTF("RPL: Forward error !\n");
|
||||||
|
/* We should try to repair it, not implemented for the moment */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
|
||||||
|
|
||||||
|
if (instance == NULL) {
|
||||||
|
PRINTF("RPL : Unknown instance : %u\n",UIP_EXT_HDR_OPT_RPL_BUF->instance);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instance->current_dag->joined) {
|
||||||
|
PRINTF("RPL : No dag in the instance\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_DOWN) {
|
||||||
|
PRINTF("RPL: Packet going down :\n");
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank>instance->current_dag->rank) {
|
||||||
|
PRINTF("RPL: Loop detected : Sender rank > our rank\n");
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) {
|
||||||
|
PRINTF("RPL: Loop detected !\n");
|
||||||
|
/* We should try to repair it, not implemented for the moment */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
PRINTF("RPL: Single error tolerated\n");
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PRINTF("RPL: Packet going up :");
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank<instance->current_dag->rank) {
|
||||||
|
PRINTF("RPL: Rank error : Sender rank < our rank\n");
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) {
|
||||||
|
PRINTF("RPL: Loop detected !\n");
|
||||||
|
/* We should try to repair it, not implemented for the moment */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
PRINTF("RPL: Single error tolerated\n");
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRINTF("RPL: rank Ok\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
void
|
||||||
|
rpl_update_header_empty(void)
|
||||||
|
{
|
||||||
|
rpl_instance_t *instance;
|
||||||
|
int uip_ext_opt_offset;
|
||||||
|
int last_uip_ext_len;
|
||||||
|
u8_t temp_len;
|
||||||
|
|
||||||
|
last_uip_ext_len=uip_ext_len;
|
||||||
|
uip_ext_len=0;
|
||||||
|
uip_ext_opt_offset = 2;
|
||||||
|
|
||||||
|
PRINTF("RPL: Verifying the presence of the RPL header option\n");
|
||||||
|
switch(UIP_IP_BUF->proto){
|
||||||
|
case UIP_PROTO_HBHO:
|
||||||
|
if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) {
|
||||||
|
PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
|
||||||
|
if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) {
|
||||||
|
PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: No Hop-by-Hop Option found, creating it\n");
|
||||||
|
if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) {
|
||||||
|
PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN);
|
||||||
|
memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN);
|
||||||
|
UIP_HBHO_BUF->next=UIP_IP_BUF->proto;
|
||||||
|
UIP_IP_BUF->proto=UIP_PROTO_HBHO;
|
||||||
|
UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags=0;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->instance=0;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=0;
|
||||||
|
uip_len+=RPL_OP_BY_OP_LEN;
|
||||||
|
temp_len=UIP_IP_BUF->len[1];
|
||||||
|
UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8);
|
||||||
|
if (UIP_IP_BUF->len[1]<temp_len) {
|
||||||
|
UIP_IP_BUF->len[0]+=1;
|
||||||
|
}
|
||||||
|
uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (UIP_EXT_HDR_OPT_BUF->type) {
|
||||||
|
case UIP_EXT_HDR_OPT_RPL:
|
||||||
|
PRINTF("RPL: Updating RPL option\n");
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank;
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: Multi Hop-by-hop options not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
int
|
||||||
|
rpl_update_header_final(uip_ipaddr_t *addr)
|
||||||
|
{
|
||||||
|
int uip_ext_opt_offset;
|
||||||
|
int last_uip_ext_len;
|
||||||
|
|
||||||
|
last_uip_ext_len=uip_ext_len;
|
||||||
|
uip_ext_len=0;
|
||||||
|
uip_ext_opt_offset = 2;
|
||||||
|
rpl_parent_t *parent;
|
||||||
|
|
||||||
|
if (UIP_IP_BUF->proto == UIP_PROTO_HBHO){
|
||||||
|
if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) {
|
||||||
|
PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) {
|
||||||
|
if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank==0) {
|
||||||
|
PRINTF("RPL: Updating RPL option\n");
|
||||||
|
if(default_instance == NULL || (!default_instance->used) || (!default_instance->current_dag->joined) ) {
|
||||||
|
PRINTF("Unable to add RPL hop-by-hop extension header : incorrect default instance\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
parent=rpl_find_parent(default_instance->current_dag,addr);
|
||||||
|
if (parent == NULL || (parent != parent->dag->preferred_parent)) {
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN;
|
||||||
|
}
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->instance=default_instance->instance_id;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=default_instance->current_dag->rank;
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
int
|
||||||
|
rpl_add_header(rpl_instance_t *instance,int down)
|
||||||
|
{
|
||||||
|
int uip_ext_opt_offset;
|
||||||
|
int last_uip_ext_len;
|
||||||
|
u8_t temp_len;
|
||||||
|
|
||||||
|
last_uip_ext_len = uip_ext_len;
|
||||||
|
uip_ext_len = 0;
|
||||||
|
uip_ext_opt_offset = 2;
|
||||||
|
|
||||||
|
if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) {
|
||||||
|
PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTF("RPL: Verifying the presence of the RPL header option\n");
|
||||||
|
switch(UIP_IP_BUF->proto){
|
||||||
|
case UIP_PROTO_HBHO:
|
||||||
|
if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) {
|
||||||
|
PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: No Hop-by-Hop Option found, creating it\n");
|
||||||
|
if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) {
|
||||||
|
PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN);
|
||||||
|
memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN);
|
||||||
|
UIP_HBHO_BUF->next=UIP_IP_BUF->proto;
|
||||||
|
UIP_IP_BUF->proto=UIP_PROTO_HBHO;
|
||||||
|
UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<<RPL_HDR_OPT_DOWN_SHIFT);
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->instance=instance->instance_id;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank;
|
||||||
|
uip_len+=RPL_OP_BY_OP_LEN;
|
||||||
|
temp_len=UIP_IP_BUF->len[1];
|
||||||
|
UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8);
|
||||||
|
if (UIP_IP_BUF->len[1]<temp_len) {
|
||||||
|
UIP_IP_BUF->len[0]+=1;
|
||||||
|
}
|
||||||
|
uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
switch (UIP_EXT_HDR_OPT_BUF->type) {
|
||||||
|
case UIP_EXT_HDR_OPT_RPL:
|
||||||
|
PRINTF("RPL: Updating RPL option\n");
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<<RPL_HDR_OPT_DOWN_SHIFT);
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->instance=instance->instance_id;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank;
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: Multi Hop-by-hop options not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
int
|
||||||
|
rpl_add_header_root(void)
|
||||||
|
{
|
||||||
|
return rpl_add_header(default_instance,1);
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
void
|
||||||
|
rpl_remove_header()
|
||||||
|
{
|
||||||
|
int last_uip_ext_len;
|
||||||
|
u8_t temp_len;
|
||||||
|
|
||||||
|
last_uip_ext_len=uip_ext_len;
|
||||||
|
uip_ext_len=0;
|
||||||
|
|
||||||
|
PRINTF("RPL: Verifying the presence of the RPL header option\n");
|
||||||
|
switch(UIP_IP_BUF->proto){
|
||||||
|
case UIP_PROTO_HBHO:
|
||||||
|
PRINTF("RPL: Removing the present RPL header option\n");
|
||||||
|
UIP_IP_BUF->proto=UIP_HBHO_BUF->next;
|
||||||
|
temp_len=UIP_IP_BUF->len[1];
|
||||||
|
uip_len-=UIP_HBHO_BUF->len + 8;
|
||||||
|
UIP_IP_BUF->len[1]-=(UIP_HBHO_BUF->len + 8);
|
||||||
|
if (UIP_IP_BUF->len[1]>temp_len) {
|
||||||
|
UIP_IP_BUF->len[0]-=1;
|
||||||
|
}
|
||||||
|
memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: No Hop-by-Hop Option found\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
u8_t
|
||||||
|
rpl_invert_header()
|
||||||
|
{
|
||||||
|
u8_t uip_ext_opt_offset;
|
||||||
|
u8_t last_uip_ext_len;
|
||||||
|
|
||||||
|
last_uip_ext_len=uip_ext_len;
|
||||||
|
uip_ext_len=0;
|
||||||
|
uip_ext_opt_offset = 2;
|
||||||
|
|
||||||
|
PRINTF("RPL: Verifying the presence of the RPL header option\n");
|
||||||
|
switch(UIP_IP_BUF->proto){
|
||||||
|
case UIP_PROTO_HBHO:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: No Hop-by-Hop Option found\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (UIP_EXT_HDR_OPT_BUF->type) {
|
||||||
|
case UIP_EXT_HDR_OPT_RPL:
|
||||||
|
PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n");
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags&=RPL_HDR_OPT_DOWN;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->flags^=RPL_HDR_OPT_DOWN;
|
||||||
|
UIP_EXT_HDR_OPT_RPL_BUF->senderrank=rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank;
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return RPL_OP_BY_OP_LEN;
|
||||||
|
default:
|
||||||
|
PRINTF("RPL: Multi Hop-by-hop options not implemented\n");
|
||||||
|
uip_ext_len=last_uip_ext_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************************************************************/
|
||||||
|
|
|
@ -75,17 +75,86 @@
|
||||||
/* This value decides which DAG instance we should participate in by default. */
|
/* This value decides which DAG instance we should participate in by default. */
|
||||||
#define RPL_DEFAULT_INSTANCE 0
|
#define RPL_DEFAULT_INSTANCE 0
|
||||||
|
|
||||||
/* This value is used to access an arbitrary DAG. It will likely be
|
/*
|
||||||
replaced when we support multiple DAGs more. */
|
* This value decides if this node must stay as a leaf or not
|
||||||
#define RPL_ANY_INSTANCE -1
|
* as allowed by draft-ietf-roll-rpl-19#section-8.5
|
||||||
|
*/
|
||||||
|
#ifdef RPL_CONF_LEAF_ONLY
|
||||||
|
#define RPL_LEAF_ONLY RPL_CONF_LEAF_ONLY
|
||||||
|
#else
|
||||||
|
#define RPL_LEAF_ONLY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum of concurent rpl-instances
|
||||||
|
*/
|
||||||
|
#ifndef RPL_CONF_MAX_INSTANCES
|
||||||
|
#define RPL_MAX_INSTANCES 1
|
||||||
|
#else
|
||||||
|
#define RPL_MAX_INSTANCES RPL_CONF_MAX_INSTANCES
|
||||||
|
#endif /* !RPL_CONF_MAX_INSTANCES */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum of concurent dodag inside an instance
|
||||||
|
*/
|
||||||
|
#ifndef RPL_CONF_MAX_DODAG_PER_INSTANCE
|
||||||
|
#define RPL_MAX_DODAG_PER_INSTANCE 2
|
||||||
|
#else
|
||||||
|
#define RPL_MAX_DODAG_PER_INSTANCE RPL_CONF_MAX_DODAG_PER_INSTANCE
|
||||||
|
#endif /* !RPL_CONF_MAX_DODAG_PER_INSTANCE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef RPL_CONF_DAO_SPECIFY_DODAG
|
||||||
|
#if RPL_MAX_DODAG_PER_INSTANCE > 1
|
||||||
|
#define RPL_DAO_SPECIFY_DODAG 1
|
||||||
|
#else /* RPL_MAX_DODAG_PER_INSTANCE > 1*/
|
||||||
|
#define RPL__DAO_SPECIFY_DODAG 0
|
||||||
|
#endif /* RPL_MAX_DODAG_PER_INSTANCE > 1 */
|
||||||
|
#else /* RPL_CONF_DAO_SPECIFY_DODAG */
|
||||||
|
#define RPL_DAO_SPECIFY_DODAG RPL_CONF_DAO_SPECIFY_DODAG
|
||||||
|
#endif /* RPL_CONF_DAO_SPECIFY_DODAG */
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* The amount of parents that this node has in a particular DAG. */
|
/* The amount of parents that this node has in a particular DAG. */
|
||||||
#define RPL_PARENT_COUNT(dag) list_length((dag)->parents)
|
#define RPL_PARENT_COUNT(dag) list_length((dag)->parents)
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
typedef uint16_t rpl_rank_t;
|
typedef uint16_t rpl_rank_t;
|
||||||
typedef uint8_t rpl_lifetime_t;
|
|
||||||
typedef uint16_t rpl_ocp_t;
|
typedef uint16_t rpl_ocp_t;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Lollipop counters */
|
||||||
|
|
||||||
|
#define RPL_LOLLIPOP_MAX_VALUE 255
|
||||||
|
#define RPL_LOLLIPOP_CIRCULAR_REGION 127
|
||||||
|
#define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16
|
||||||
|
#define RPL_LOLLIPOP_INIT RPL_LOLLIPOP_MAX_VALUE - RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1
|
||||||
|
#define RPL_LOLLIPOP_INCREMENT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION ?\
|
||||||
|
(counter == RPL_LOLLIPOP_MAX_VALUE ? counter=0 : ++counter):\
|
||||||
|
(counter == RPL_LOLLIPOP_CIRCULAR_REGION ? counter=0 : ++counter))
|
||||||
|
#define RPL_LOLLIPOP_IS_INIT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION)
|
||||||
|
#define RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B) (((A < B) && (RPL_LOLLIPOP_CIRCULAR_REGION + 1 - B + A < RPL_LOLLIPOP_SEQUENCE_WINDOWS)) || \
|
||||||
|
((A > B) && (A - B < RPL_LOLLIPOP_SEQUENCE_WINDOWS)))
|
||||||
|
#define RPL_LOLLIPOP_GREATER_THAN(A,B) ((A > RPL_LOLLIPOP_CIRCULAR_REGION )?\
|
||||||
|
((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\
|
||||||
|
RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B):\
|
||||||
|
0):\
|
||||||
|
((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\
|
||||||
|
1:\
|
||||||
|
RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B)))
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* RPL IPv6 extension header option. */
|
||||||
|
#define RPL_HDR_OPT_LEN 4
|
||||||
|
#define RPL_OP_BY_OP_LEN RPL_HDR_OPT_LEN+2+2
|
||||||
|
#define RPL_HDR_OPT_DOWN 0x80
|
||||||
|
#define RPL_HDR_OPT_DOWN_SHIFT 7
|
||||||
|
#define RPL_HDR_OPT_RANK_ERR 0x40
|
||||||
|
#define RPL_HDR_OPT_RANK_ERR_SHIFT 6
|
||||||
|
#define RPL_HDR_OPT_FWD_ERR 0x20
|
||||||
|
#define RPL_HDR_OPT_FWD_ERR_SHIFT 5
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* 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 */
|
||||||
|
@ -139,6 +208,7 @@ struct rpl_metric_container {
|
||||||
};
|
};
|
||||||
typedef struct rpl_metric_container rpl_metric_container_t;
|
typedef struct rpl_metric_container rpl_metric_container_t;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
struct rpl_instance;
|
||||||
struct rpl_dag;
|
struct rpl_dag;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
struct rpl_parent {
|
struct rpl_parent {
|
||||||
|
@ -153,6 +223,35 @@ struct rpl_parent {
|
||||||
};
|
};
|
||||||
typedef struct rpl_parent rpl_parent_t;
|
typedef struct rpl_parent rpl_parent_t;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* RPL DIO prefix suboption */
|
||||||
|
struct rpl_prefix {
|
||||||
|
uip_ipaddr_t prefix;
|
||||||
|
uint32_t lifetime;
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t flags;
|
||||||
|
};
|
||||||
|
typedef struct rpl_prefix rpl_prefix_t;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Directed Acyclic Graph */
|
||||||
|
struct rpl_dag {
|
||||||
|
uip_ipaddr_t dag_id;
|
||||||
|
rpl_rank_t min_rank; /* should be reset per DODAG iteration! */
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t grounded;
|
||||||
|
uint8_t preference;
|
||||||
|
uint8_t used;
|
||||||
|
/* live data for the DAG */
|
||||||
|
uint8_t joined;
|
||||||
|
rpl_parent_t *preferred_parent;
|
||||||
|
rpl_rank_t rank;
|
||||||
|
struct rpl_instance *instance;
|
||||||
|
void *parent_list;
|
||||||
|
list_t parents;
|
||||||
|
rpl_prefix_t prefix_info;
|
||||||
|
};
|
||||||
|
typedef struct rpl_dag rpl_dag_t;
|
||||||
|
typedef struct rpl_instance rpl_instance_t;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
* API for RPL objective functions (OF)
|
* API for RPL objective functions (OF)
|
||||||
*
|
*
|
||||||
|
@ -171,6 +270,10 @@ typedef struct rpl_parent rpl_parent_t;
|
||||||
*
|
*
|
||||||
* Compares two parents and returns the best one, according to the OF.
|
* Compares two parents and returns the best one, according to the OF.
|
||||||
*
|
*
|
||||||
|
* best_dag(dodag1, dodag2)
|
||||||
|
*
|
||||||
|
* Compares two dodags and returns the best one, according to the OF.
|
||||||
|
*
|
||||||
* calculate_rank(parent, base_rank)
|
* calculate_rank(parent, base_rank)
|
||||||
*
|
*
|
||||||
* Calculates a rank value using the parent rank and a base rank.
|
* Calculates a rank value using the parent rank and a base rank.
|
||||||
|
@ -188,47 +291,33 @@ struct rpl_of {
|
||||||
void (*reset)(struct rpl_dag *);
|
void (*reset)(struct rpl_dag *);
|
||||||
void (*parent_state_callback)(rpl_parent_t *, int, int);
|
void (*parent_state_callback)(rpl_parent_t *, int, int);
|
||||||
rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *);
|
rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *);
|
||||||
|
rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *);
|
||||||
rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t);
|
rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t);
|
||||||
void (*update_metric_container)(struct rpl_dag *);
|
void (*update_metric_container)( rpl_instance_t *);
|
||||||
rpl_ocp_t ocp;
|
rpl_ocp_t ocp;
|
||||||
};
|
};
|
||||||
typedef struct rpl_of rpl_of_t;
|
typedef struct rpl_of rpl_of_t;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* RPL DIO prefix suboption */
|
/* Instance */
|
||||||
struct rpl_prefix {
|
struct rpl_instance {
|
||||||
uip_ipaddr_t prefix;
|
|
||||||
uint32_t lifetime;
|
|
||||||
uint8_t length;
|
|
||||||
uint8_t flags;
|
|
||||||
};
|
|
||||||
typedef struct rpl_prefix rpl_prefix_t;
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
/* Directed Acyclic Graph */
|
|
||||||
struct rpl_dag {
|
|
||||||
/* DAG configuration */
|
/* DAG configuration */
|
||||||
rpl_metric_container_t mc;
|
rpl_metric_container_t mc;
|
||||||
rpl_of_t *of;
|
rpl_of_t *of;
|
||||||
uip_ipaddr_t dag_id;
|
uint8_t instance_id;
|
||||||
|
rpl_dag_t *current_dag;
|
||||||
|
uint8_t used;
|
||||||
|
rpl_dag_t dag_table[RPL_MAX_DODAG_PER_INSTANCE];
|
||||||
/* The current default router - used for routing "upwards" */
|
/* The current default router - used for routing "upwards" */
|
||||||
uip_ds6_defrt_t *def_route;
|
uip_ds6_defrt_t *def_route;
|
||||||
rpl_rank_t rank;
|
|
||||||
rpl_rank_t min_rank; /* should be reset per DODAG iteration! */
|
|
||||||
uint8_t dtsn_out;
|
uint8_t dtsn_out;
|
||||||
uint8_t instance_id;
|
|
||||||
uint8_t version;
|
|
||||||
uint8_t grounded;
|
|
||||||
uint8_t mop;
|
uint8_t mop;
|
||||||
uint8_t preference;
|
|
||||||
uint8_t dio_intdoubl;
|
uint8_t dio_intdoubl;
|
||||||
uint8_t dio_intmin;
|
uint8_t dio_intmin;
|
||||||
uint8_t dio_redundancy;
|
uint8_t dio_redundancy;
|
||||||
rpl_rank_t max_rankinc;
|
rpl_rank_t max_rankinc;
|
||||||
rpl_rank_t min_hoprankinc;
|
rpl_rank_t min_hoprankinc;
|
||||||
uint8_t used;
|
|
||||||
uint8_t default_lifetime;
|
uint8_t default_lifetime;
|
||||||
uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */
|
uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */
|
||||||
/* live data for the DAG */
|
|
||||||
uint8_t joined;
|
|
||||||
uint8_t dio_intcurrent;
|
uint8_t dio_intcurrent;
|
||||||
uint8_t dio_send; /* for keeping track of which mode the timer is in
|
uint8_t dio_send; /* for keeping track of which mode the timer is in
|
||||||
*/
|
*/
|
||||||
|
@ -241,19 +330,21 @@ struct rpl_dag {
|
||||||
uint32_t dio_next_delay; /* delay for completion of dio interval */
|
uint32_t dio_next_delay; /* delay for completion of dio interval */
|
||||||
struct ctimer dio_timer;
|
struct ctimer dio_timer;
|
||||||
struct ctimer dao_timer;
|
struct ctimer dao_timer;
|
||||||
rpl_parent_t *preferred_parent;
|
|
||||||
void *parent_list;
|
|
||||||
list_t parents;
|
|
||||||
rpl_prefix_t prefix_info;
|
|
||||||
};
|
};
|
||||||
typedef struct rpl_dag rpl_dag_t;
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Public RPL functions. */
|
/* Public RPL functions. */
|
||||||
void rpl_init(void);
|
void rpl_init(void);
|
||||||
rpl_dag_t *rpl_set_root(uip_ipaddr_t *);
|
rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id);
|
||||||
int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len);
|
int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len);
|
||||||
int rpl_repair_dag(rpl_dag_t *dag);
|
int rpl_repair_root(uint8_t instance_id);
|
||||||
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from);
|
int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from);
|
||||||
rpl_dag_t *rpl_get_dag(int instance_id);
|
rpl_dag_t *rpl_get_any_dag(void);
|
||||||
|
rpl_dag_t *rpl_get_dodag(uint8_t instance_id,uip_ipaddr_t * dag_id);
|
||||||
|
rpl_instance_t *rpl_get_instance(uint8_t instance_id);
|
||||||
|
int rpl_add_header(rpl_instance_t *instance,int down);
|
||||||
|
int rpl_add_header_root(void);
|
||||||
|
void rpl_remove_header(void);
|
||||||
|
u8_t rpl_invert_header(void);
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#endif /* RPL_H */
|
#endif /* RPL_H */
|
||||||
|
|
|
@ -227,7 +227,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
||||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
||||||
}
|
}
|
||||||
|
|
||||||
dag = rpl_set_root((uip_ip6addr_t *)dag_id);
|
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)dag_id);
|
||||||
if(dag != NULL) {
|
if(dag != NULL) {
|
||||||
rpl_set_prefix(dag, &prefix, 64);
|
rpl_set_prefix(dag, &prefix, 64);
|
||||||
PRINTF("created a new RPL dag\n");
|
PRINTF("created a new RPL dag\n");
|
||||||
|
@ -245,7 +245,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
||||||
PROCESS_YIELD();
|
PROCESS_YIELD();
|
||||||
if (ev == sensors_event && data == &button_sensor) {
|
if (ev == sensors_event && data == &button_sensor) {
|
||||||
PRINTF("Initiating global repair\n");
|
PRINTF("Initiating global repair\n");
|
||||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ collect_common_net_print(void)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
int i;
|
int i;
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
/* Let's suppose we have only one instance */
|
||||||
|
dag = rpl_get_any_dag();
|
||||||
if(dag->preferred_parent != NULL) {
|
if(dag->preferred_parent != NULL) {
|
||||||
PRINTF("Preferred parent: ");
|
PRINTF("Preferred parent: ");
|
||||||
PRINT6ADDR(&dag->preferred_parent->addr);
|
PRINT6ADDR(&dag->preferred_parent->addr);
|
||||||
|
@ -128,7 +129,8 @@ collect_common_send(void)
|
||||||
rimeaddr_copy(&parent, &rimeaddr_null);
|
rimeaddr_copy(&parent, &rimeaddr_null);
|
||||||
parent_etx = 0;
|
parent_etx = 0;
|
||||||
|
|
||||||
dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
|
/* Let's suppose we have only one instance */
|
||||||
|
dag = rpl_get_any_dag();
|
||||||
if(dag != NULL) {
|
if(dag != NULL) {
|
||||||
preferred_parent = dag->preferred_parent;
|
preferred_parent = dag->preferred_parent;
|
||||||
if(preferred_parent != NULL) {
|
if(preferred_parent != NULL) {
|
||||||
|
|
|
@ -151,8 +151,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
||||||
root_if = uip_ds6_addr_lookup(&ipaddr);
|
root_if = uip_ds6_addr_lookup(&ipaddr);
|
||||||
if(root_if != NULL) {
|
if(root_if != NULL) {
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
rpl_set_root((uip_ip6addr_t *)&ipaddr);
|
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr);
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
|
||||||
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
||||||
rpl_set_prefix(dag, &ipaddr, 64);
|
rpl_set_prefix(dag, &ipaddr, 64);
|
||||||
PRINTF("created a new RPL dag\n");
|
PRINTF("created a new RPL dag\n");
|
||||||
|
@ -181,7 +180,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
||||||
tcpip_handler();
|
tcpip_handler();
|
||||||
} else if (ev == sensors_event && data == &button_sensor) {
|
} else if (ev == sensors_event && data == &button_sensor) {
|
||||||
PRINTF("Initiaing global repair\n");
|
PRINTF("Initiaing global repair\n");
|
||||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
||||||
root_if = uip_ds6_addr_lookup(&ipaddr);
|
root_if = uip_ds6_addr_lookup(&ipaddr);
|
||||||
if(root_if != NULL) {
|
if(root_if != NULL) {
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
rpl_set_root((uip_ip6addr_t *)&ipaddr);
|
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr);
|
||||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
|
||||||
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
||||||
rpl_set_prefix(dag, &ipaddr, 64);
|
rpl_set_prefix(dag, &ipaddr, 64);
|
||||||
PRINTF("created a new RPL dag\n");
|
PRINTF("created a new RPL dag\n");
|
||||||
|
@ -164,7 +163,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
||||||
tcpip_handler();
|
tcpip_handler();
|
||||||
} else if (ev == sensors_event && data == &button_sensor) {
|
} else if (ev == sensors_event && data == &button_sensor) {
|
||||||
PRINTF("Initiaing global repair\n");
|
PRINTF("Initiaing global repair\n");
|
||||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -620,11 +620,11 @@ extern uip_ds6_netif_t uip_ds6_if;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)));
|
PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_root(RPL_DEFAULT_INSTANCE));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
rpl_local_repair(rpl_get_dag(RPL_ANY_INSTANCE));
|
rpl_local_repair(rpl_get_any_dag());
|
||||||
PRINTF_P(PSTR("Local repair initiated\n\r"));
|
PRINTF_P(PSTR("Local repair initiated\n\r"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
||||||
{ rpl_dag_t *dag;
|
{ rpl_dag_t *dag;
|
||||||
char buf[sizeof(dag_id)];
|
char buf[sizeof(dag_id)];
|
||||||
memcpy_P(buf,dag_id,sizeof(dag_id));
|
memcpy_P(buf,dag_id,sizeof(dag_id));
|
||||||
dag = rpl_set_root((uip_ip6addr_t *)buf);
|
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)buf);
|
||||||
|
|
||||||
/* Assign separate addresses to the jackdaw uip stack and the host network interface, but with the same prefix */
|
/* Assign separate addresses to the jackdaw uip stack and the host network interface, but with the same prefix */
|
||||||
/* E.g. bbbb::200 to the jackdaw and bbbb::1 to the host network interface with $ip -6 address add bbbb::1/64 dev usb0 */
|
/* E.g. bbbb::200 to the jackdaw and bbbb::1 to the host network interface with $ip -6 address add bbbb::1/64 dev usb0 */
|
||||||
|
@ -192,8 +192,6 @@ PROCESS_THREAD(border_router_process, ev, data)
|
||||||
while(1) {
|
while(1) {
|
||||||
PROCESS_YIELD();
|
PROCESS_YIELD();
|
||||||
/* Local and global dag repair can be done from the jackdaw menu */
|
/* Local and global dag repair can be done from the jackdaw menu */
|
||||||
// rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64);
|
|
||||||
// rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ void set_net_address(void)
|
||||||
print_addresses();
|
print_addresses();
|
||||||
|
|
||||||
#if RPL_BORDER_ROUTER
|
#if RPL_BORDER_ROUTER
|
||||||
dag = rpl_set_root(&ipaddr);
|
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,&ipaddr);
|
||||||
if(dag != NULL) {
|
if(dag != NULL) {
|
||||||
PRINTF("This node is setted as root of a DAG.\r\n");
|
PRINTF("This node is setted as root of a DAG.\r\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue