Implement RPL non-storing mode
This commit is contained in:
parent
d14b76d869
commit
b3e31e1456
17 changed files with 1149 additions and 278 deletions
|
@ -51,6 +51,7 @@
|
|||
#include "net/ipv6/uip-nd6.h"
|
||||
#include "net/ipv6/uip-icmp6.h"
|
||||
#include "net/rpl/rpl-private.h"
|
||||
#include "net/rpl/rpl-ns.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/ipv6/multicast/uip-mcast6.h"
|
||||
#include "random.h"
|
||||
|
@ -119,6 +120,7 @@ find_route_entry_by_dao_ack(uint8_t seq)
|
|||
}
|
||||
#endif /* RPL_WITH_DAO_ACK */
|
||||
|
||||
#if RPL_WITH_STORING
|
||||
/* prepare for forwarding of DAO */
|
||||
static uint8_t
|
||||
prepare_for_dao_fwd(uint8_t sequence, uip_ds6_route_t *rep)
|
||||
|
@ -132,6 +134,7 @@ prepare_for_dao_fwd(uint8_t sequence, uip_ds6_route_t *rep)
|
|||
RPL_ROUTE_SET_DAO_PENDING(rep);
|
||||
return dao_sequence;
|
||||
}
|
||||
#endif /* RPL_WITH_STORING */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
get_global_addr(uip_ipaddr_t *addr)
|
||||
|
@ -626,8 +629,9 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
dao_input(void)
|
||||
dao_input_storing(void)
|
||||
{
|
||||
#if RPL_WITH_STORING
|
||||
uip_ipaddr_t dao_sender_addr;
|
||||
rpl_dag_t *dag;
|
||||
rpl_instance_t *instance;
|
||||
|
@ -665,11 +669,6 @@ dao_input(void)
|
|||
instance_id = buffer[pos++];
|
||||
|
||||
instance = rpl_get_instance(instance_id);
|
||||
if(instance == NULL) {
|
||||
PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n",
|
||||
instance_id);
|
||||
goto discard;
|
||||
}
|
||||
|
||||
lifetime = instance->default_lifetime;
|
||||
|
||||
|
@ -685,7 +684,7 @@ dao_input(void)
|
|||
if(flags & RPL_DAO_D_FLAG) {
|
||||
if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) {
|
||||
PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n");
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
pos += 16;
|
||||
}
|
||||
|
@ -710,7 +709,7 @@ dao_input(void)
|
|||
DAG_RANK(parent->rank, instance), DAG_RANK(dag->rank, instance));
|
||||
parent->rank = INFINITE_RANK;
|
||||
parent->flags |= RPL_PARENT_FLAG_UPDATED;
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we get the DAO from our parent, we also have a loop. */
|
||||
|
@ -718,7 +717,7 @@ dao_input(void)
|
|||
PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n");
|
||||
parent->rank = INFINITE_RANK;
|
||||
parent->flags |= RPL_PARENT_FLAG_UPDATED;
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -805,7 +804,7 @@ dao_input(void)
|
|||
dao_ack_output(instance, &dao_sender_addr, sequence,
|
||||
RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
|
||||
}
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
|
||||
PRINTF("RPL: Adding DAO route\n");
|
||||
|
@ -823,7 +822,7 @@ dao_input(void)
|
|||
is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT :
|
||||
RPL_DAO_ACK_UNABLE_TO_ACCEPT);
|
||||
}
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
|
||||
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
|
||||
|
@ -836,7 +835,7 @@ dao_input(void)
|
|||
is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT :
|
||||
RPL_DAO_ACK_UNABLE_TO_ACCEPT);
|
||||
}
|
||||
goto discard;
|
||||
return;
|
||||
}
|
||||
|
||||
/* set lifetime and clear NOPATH bit */
|
||||
|
@ -892,6 +891,141 @@ fwd_dao:
|
|||
RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
|
||||
}
|
||||
}
|
||||
#endif /* RPL_WITH_STORING */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
dao_input_nonstoring(void)
|
||||
{
|
||||
#if RPL_WITH_NON_STORING
|
||||
uip_ipaddr_t dao_sender_addr;
|
||||
uip_ipaddr_t dao_parent_addr;
|
||||
rpl_dag_t *dag;
|
||||
rpl_instance_t *instance;
|
||||
unsigned char *buffer;
|
||||
uint16_t sequence;
|
||||
uint8_t instance_id;
|
||||
uint8_t lifetime;
|
||||
uint8_t prefixlen;
|
||||
uint8_t flags;
|
||||
uint8_t subopt_type;
|
||||
uip_ipaddr_t prefix;
|
||||
uint8_t buffer_length;
|
||||
int pos;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
prefixlen = 0;
|
||||
|
||||
uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr);
|
||||
memset(&dao_parent_addr, 0, 16);
|
||||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
buffer_length = uip_len - uip_l3_icmp_hdr_len;
|
||||
|
||||
pos = 0;
|
||||
instance_id = buffer[pos++];
|
||||
instance = rpl_get_instance(instance_id);
|
||||
lifetime = instance->default_lifetime;
|
||||
|
||||
flags = buffer[pos++];
|
||||
/* reserved */
|
||||
pos++;
|
||||
sequence = buffer[pos++];
|
||||
|
||||
dag = instance->current_dag;
|
||||
/* Is the DAG ID present? */
|
||||
if(flags & RPL_DAO_D_FLAG) {
|
||||
if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) {
|
||||
PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n");
|
||||
return;
|
||||
}
|
||||
pos += 16;
|
||||
}
|
||||
|
||||
/* Check if there are any RPL options present. */
|
||||
for(i = pos; i < buffer_length; i += len) {
|
||||
subopt_type = buffer[i];
|
||||
if(subopt_type == RPL_OPTION_PAD1) {
|
||||
len = 1;
|
||||
} else {
|
||||
/* The option consists of a two-byte header and a payload. */
|
||||
len = 2 + buffer[i + 1];
|
||||
}
|
||||
|
||||
switch(subopt_type) {
|
||||
case RPL_OPTION_TARGET:
|
||||
/* Handle the target option. */
|
||||
prefixlen = buffer[i + 3];
|
||||
memset(&prefix, 0, sizeof(prefix));
|
||||
memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT);
|
||||
break;
|
||||
case RPL_OPTION_TRANSIT:
|
||||
/* The path sequence and control are ignored. */
|
||||
/* pathcontrol = buffer[i + 3];
|
||||
pathsequence = buffer[i + 4];*/
|
||||
lifetime = buffer[i + 5];
|
||||
if(len >= 20) {
|
||||
memcpy(&dao_parent_addr, buffer + i + 6, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ",
|
||||
(unsigned)lifetime, (unsigned)prefixlen);
|
||||
PRINT6ADDR(&prefix);
|
||||
PRINTF(", parent: ");
|
||||
PRINT6ADDR(&dao_parent_addr);
|
||||
PRINTF(" \n");
|
||||
|
||||
if(lifetime == RPL_ZERO_LIFETIME) {
|
||||
PRINTF("RPL: No-Path DAO received\n");
|
||||
rpl_ns_expire_parent(dag, &prefix, &dao_parent_addr);
|
||||
} else {
|
||||
if(rpl_ns_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) {
|
||||
PRINTF("RPL: failed to add link\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & RPL_DAO_K_FLAG) {
|
||||
PRINTF("RPL: Sending DAO ACK\n");
|
||||
uip_clear_buf();
|
||||
dao_ack_output(instance, &dao_sender_addr, sequence,
|
||||
RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
|
||||
}
|
||||
#endif /* RPL_WITH_NON_STORING */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
dao_input(void)
|
||||
{
|
||||
rpl_instance_t *instance;
|
||||
uint8_t instance_id;
|
||||
|
||||
/* Destination Advertisement Object */
|
||||
PRINTF("RPL: Received a DAO from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
instance_id = UIP_ICMP_PAYLOAD[0];
|
||||
instance = rpl_get_instance(instance_id);
|
||||
if(instance == NULL) {
|
||||
PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n",
|
||||
instance_id);
|
||||
goto discard;
|
||||
}
|
||||
|
||||
if(instance->mop != RPL_MOP_NON_STORING) {
|
||||
if(RPL_IS_STORING(instance)) {
|
||||
dao_input_storing();
|
||||
}
|
||||
} else {
|
||||
if(RPL_IS_NON_STORING(instance)) {
|
||||
dao_input_nonstoring();
|
||||
}
|
||||
}
|
||||
|
||||
discard:
|
||||
uip_clear_buf();
|
||||
|
@ -1006,6 +1140,8 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix,
|
|||
unsigned char *buffer;
|
||||
uint8_t prefixlen;
|
||||
int pos;
|
||||
uip_ipaddr_t *parent_ipaddr = NULL;
|
||||
uip_ipaddr_t *dest_ipaddr = NULL;
|
||||
|
||||
/* Destination Advertisement Object */
|
||||
|
||||
|
@ -1019,6 +1155,12 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix,
|
|||
return;
|
||||
}
|
||||
|
||||
parent_ipaddr = rpl_get_parent_ipaddr(parent);
|
||||
if(parent_ipaddr == NULL) {
|
||||
PRINTF("RPL dao_output_target error parent IP address NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dag = parent->dag;
|
||||
if(dag == NULL) {
|
||||
PRINTF("RPL dao_output_target error dag NULL\n");
|
||||
|
@ -1071,21 +1213,37 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix,
|
|||
|
||||
/* Create a transit information sub-option. */
|
||||
buffer[pos++] = RPL_OPTION_TRANSIT;
|
||||
buffer[pos++] = 4;
|
||||
buffer[pos++] = (instance->mop != RPL_MOP_NON_STORING) ? 4 : 20;
|
||||
buffer[pos++] = 0; /* flags - ignored */
|
||||
buffer[pos++] = 0; /* path control - ignored */
|
||||
buffer[pos++] = 0; /* path seq - ignored */
|
||||
buffer[pos++] = lifetime;
|
||||
|
||||
if(instance->mop != RPL_MOP_NON_STORING) {
|
||||
/* Send DAO to parent */
|
||||
dest_ipaddr = parent_ipaddr;
|
||||
} else {
|
||||
/* Include parent global IP address */
|
||||
memcpy(buffer + pos, &parent->dag->dag_id, 8); /* Prefix */
|
||||
pos += 8;
|
||||
memcpy(buffer + pos, ((const unsigned char *)parent_ipaddr) + 8, 8); /* Interface identifier */
|
||||
pos += 8;
|
||||
/* Send DAO to root */
|
||||
dest_ipaddr = &parent->dag->dag_id;
|
||||
}
|
||||
|
||||
PRINTF("RPL: Sending a %sDAO with sequence number %u, lifetime %u, prefix ",
|
||||
lifetime == RPL_ZERO_LIFETIME ? "No-Path " : "", seq_no, lifetime);
|
||||
|
||||
PRINT6ADDR(prefix);
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINT6ADDR(dest_ipaddr);
|
||||
PRINTF(" , parent ");
|
||||
PRINT6ADDR(parent_ipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
if(rpl_get_parent_ipaddr(parent) != NULL) {
|
||||
uip_icmp6_send(rpl_get_parent_ipaddr(parent), ICMP6_RPL, RPL_CODE_DAO, pos);
|
||||
if(dest_ipaddr != NULL) {
|
||||
uip_icmp6_send(dest_ipaddr, ICMP6_RPL, RPL_CODE_DAO, pos);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue