Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki

This commit is contained in:
Nicolas Tsiftes 2011-12-08 17:10:42 +01:00
commit 26bc3734eb
29 changed files with 1982 additions and 967 deletions

View file

@ -54,9 +54,24 @@
#define PRINTADDR(addr) #define PRINTADDR(addr)
#endif #endif
/** \brief The sequence number (0x00 - 0xff) added to the transmitted
* data or MAC command frame. The default is a random value within
* the range.
*/
static uint8_t mac_dsn; static uint8_t mac_dsn;
static uint8_t initialized = 0; static uint8_t initialized = 0;
/** \brief The 16-bit identifier of the PAN on which the device is
* sending to. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_dst_pan_id = IEEE802154_PANID; static const uint16_t mac_dst_pan_id = IEEE802154_PANID;
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_src_pan_id = IEEE802154_PANID; static const uint16_t mac_src_pan_id = IEEE802154_PANID;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -145,7 +160,7 @@ create(void)
/* Set the source PAN ID to the global variable. */ /* Set the source PAN ID to the global variable. */
params.src_pid = mac_src_pan_id; params.src_pid = mac_src_pan_id;
/* /*
* Set up the source address using only the long address mode for * Set up the source address using only the long address mode for
* phase 1. * phase 1.

View file

@ -39,6 +39,8 @@
#include "net/neighbor-info.h" #include "net/neighbor-info.h"
#include "net/neighbor-attr.h" #include "net/neighbor-attr.h"
#include "net/uip-ds6.h"
#include "net/uip-nd6.h"
#define DEBUG DEBUG_NONE #define DEBUG DEBUG_NONE
#include "net/uip-debug.h" #include "net/uip-debug.h"
@ -104,6 +106,9 @@ neighbor_info_packet_sent(int status, int numtx)
{ {
const rimeaddr_t *dest; const rimeaddr_t *dest;
link_metric_t packet_metric; link_metric_t packet_metric;
#if UIP_DS6_LL_NUD
uip_ds6_nbr_t *nbr;
#endif /* UIP_DS6_LL_NUD */
dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
if(rimeaddr_cmp(dest, &rimeaddr_null)) { if(rimeaddr_cmp(dest, &rimeaddr_null)) {
@ -119,6 +124,17 @@ neighbor_info_packet_sent(int status, int numtx)
switch(status) { switch(status) {
case MAC_TX_OK: case MAC_TX_OK:
add_neighbor(dest); add_neighbor(dest);
#if UIP_DS6_LL_NUD
nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest);
if(nbr != NULL &&
(nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) {
nbr->state = REACHABLE;
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
PRINTF("neighbor-info : received a link layer ACK : ");
PRINTLLADDR((uip_lladdr_t *)dest);
PRINTF(" is reachable.\n");
}
#endif /* UIP_DS6_LL_NUD */
break; break;
case MAC_TX_NOACK: case MAC_TX_NOACK:
packet_metric = ETX_NOACK_PENALTY; packet_metric = ETX_NOACK_PENALTY;

View file

@ -1,2 +1,2 @@
CONTIKI_SOURCEFILES += rpl.c rpl-dag.c rpl-icmp6.c rpl-timers.c \ CONTIKI_SOURCEFILES += rpl.c rpl-dag.c rpl-icmp6.c rpl-timers.c \
rpl-of-etx.c rpl-of-etx.c rpl-ext-header.c

1086
core/net/rpl/rpl-dag.c Normal file → Executable file

File diff suppressed because it is too large Load diff

293
core/net/rpl/rpl-ext-header.c Executable file
View file

@ -0,0 +1,293 @@
/**
* \addtogroup uip6
* @{
*/
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Management of extension headers for ContikiRPL.
*
* \author Vincent Brillault <vincent.brillault@imag.fr>,
* Joakim Eriksson <joakime@sics.se>,
* Niclas Finne <nfi@sics.se>,
* Nicolas Tsiftes <nvt@sics.se>.
*/
#include "net/uip.h"
#include "net/tcpip.h"
#include "net/uip-ds6.h"
#include "net/rpl/rpl-private.h"
#define DEBUG DEBUG_NONE
#include "net/uip-debug.h"
#include <limits.h>
#include <string.h>
/************************************************************************/
#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_HOP_BY_HOP_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])
/************************************************************************/
int
rpl_verify_header(int uip_ext_opt_offset)
{
rpl_instance_t *instance;
long diff;
int down;
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;
}
down = 0;
if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
down = 1;
}
PRINTF("RPL: Packet going %s\n", down == 1 ? "down" : "up");
diff = UIP_EXT_HDR_OPT_RPL_BUF->senderrank - instance->current_dag->rank;
if((down && diff > 0) || (!down && diff < 0)) {
PRINTF("RPL: Loop detected\n");
if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
PRINTF("RPL: Rank error signalled in RPL option!\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;
}
/************************************************************************/
static void
set_rpl_opt(unsigned uip_ext_opt_offset)
{
uint8_t temp_len;
memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN);
memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
UIP_HBHO_BUF->next = UIP_IP_BUF->proto;
UIP_IP_BUF->proto = UIP_PROTO_HBHO;
UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_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_HOP_BY_HOP_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]++;
}
}
/************************************************************************/
void
rpl_update_header_empty(void)
{
rpl_instance_t *instance;
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;
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_HOP_BY_HOP_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("RPL: Unable to add 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_HOP_BY_HOP_LEN > UIP_LINK_MTU) {
PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n");
uip_ext_len = last_uip_ext_len;
return;
}
set_rpl_opt(uip_ext_opt_offset);
uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_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)
{
rpl_parent_t *parent;
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;
if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) {
if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_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("RPL: Unable to add 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;
}
/************************************************************************/
void
rpl_remove_header(void)
{
int last_uip_ext_len;
uint8_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 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]--;
}
memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN);
break;
default:
PRINTF("RPL: No hop-by-hop Option found\n");
}
}
/************************************************************************/
uint8_t
rpl_invert_header(void)
{
uint8_t uip_ext_opt_offset;
uint8_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 (switching direction)\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_HOP_BY_HOP_LEN;
default:
PRINTF("RPL: Multi Hop-by-hop options not implemented\n");
uip_ext_len = last_uip_ext_len;
return 0;
}
}
/************************************************************************/

215
core/net/rpl/rpl-icmp6.c Normal file → Executable file
View file

@ -81,8 +81,17 @@ void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *);
void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *);
#endif #endif
static uint8_t dao_sequence = RPL_LOLLIPOP_INIT;
/* some debug callbacks useful when debugging RPL networks */
#ifdef RPL_DEBUG_DIO_INPUT
void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *);
#endif
#ifdef RPL_DEBUG_DAO_OUTPUT
void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *);
#endif
static uint8_t dao_sequence;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
get_global_addr(uip_ipaddr_t *addr) get_global_addr(uip_ipaddr_t *addr)
@ -135,21 +144,27 @@ set16(uint8_t *buffer, int pos, uint16_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(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { #if RPL_LEAF_ONLY
PRINTF("RPL: Multicast DIS => reset DIO timer\n"); if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
rpl_reset_dio_timer(dag, 0); #else /* !RPL_LEAF_ONLY */
} else { if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
PRINTF("RPL: Unicast DIS, reply to sender\n"); PRINTF("RPL: Multicast DIS => reset DIO timer\n");
dio_output(dag, &UIP_IP_BUF->srcipaddr); rpl_reset_dio_timer(instance, 0);
} else {
#endif /* !RPL_LEAF_ONLY */
PRINTF("RPL: Unicast DIS, reply to sender\n");
dio_output(instance, &UIP_IP_BUF->srcipaddr);
}
} }
} }
} }
@ -224,7 +239,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. */
@ -236,6 +251,7 @@ dio_input(void)
dio.rank = get16(buffer, i); dio.rank = get16(buffer, i);
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;
@ -249,6 +265,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];
@ -274,7 +294,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;
@ -375,19 +394,35 @@ 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
set16(buffer, pos, INFINITE_RANK);
#else /* RPL_LEAF_ONLY */
set16(buffer, pos, dag->rank); set16(buffer, pos, dag->rank);
#endif /* RPL_LEAF_ONLY */
pos += 2; pos += 2;
buffer[pos] = 0; buffer[pos] = 0;
@ -395,8 +430,15 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
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->dtsn_out; buffer[pos] |= dag->preference & RPL_DIO_PREFERENCE_MASK;
pos++;
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 */
@ -405,48 +447,49 @@ 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_OPTION_DAG_METRIC_CONTAINER; buffer[pos++] = RPL_OPTION_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;
set16(buffer, pos, dag->mc.obj.etx); set16(buffer, pos, instance->mc.obj.etx);
pos += 2; pos += 2;
} 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;
} }
} }
#endif /* !RPL_LEAF_ONLY */
/* Always add a DAG configuration option. */ /* Always add a DAG configuration option. */
buffer[pos++] = RPL_OPTION_DAG_CONF; buffer[pos++] = RPL_OPTION_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;
set16(buffer, pos, dag->max_rankinc); set16(buffer, pos, instance->max_rankinc);
pos += 2; pos += 2;
set16(buffer, pos, dag->min_hoprankinc); set16(buffer, pos, instance->min_hoprankinc);
pos += 2; pos += 2;
/* OCP is in the DAG_CONF option */ /* OCP is in the DAG_CONF option */
set16(buffer, pos, dag->of->ocp); set16(buffer, pos, instance->of->ocp);
pos += 2; pos += 2;
buffer[pos++] = 0; /* reserved */ buffer[pos++] = 0; /* reserved */
buffer[pos++] = dag->default_lifetime; buffer[pos++] = instance->default_lifetime;
set16(buffer, pos, dag->lifetime_unit); set16(buffer, pos, instance->lifetime_unit);
pos += 2; pos += 2;
/* Check if we have a prefix to send also. */ /* Check if we have a prefix to send also. */
@ -471,19 +514,27 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
dag->prefix_info.length); dag->prefix_info.length);
} }
#if RPL_LEAF_ONLY
PRINTF("RPL: Sending unicast-DIO with rank %u to ",
(unsigned)dag->rank);
PRINT6ADDR(uc_addr);
PRINTF("\n");
uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos);
#else /* RPL_LEAF_ONLY */
/* Unicast requests get unicast replies! */ /* Unicast requests get unicast replies! */
if(uc_addr == NULL) { if(uc_addr == NULL) {
PRINTF("RPL: Sending a multicast-DIO with rank %u\n", PRINTF("RPL: Sending a multicast-DIO with rank %u\n",
(unsigned)dag->rank); (unsigned)instance->current_dag->rank);
uip_create_linklocal_rplnodes_mcast(&addr); uip_create_linklocal_rplnodes_mcast(&addr);
uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos); uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos);
} else { } else {
PRINTF("RPL: Sending unicast-DIO with rank %u to ", PRINTF("RPL: Sending unicast-DIO with rank %u to ",
(unsigned)dag->rank); (unsigned)instance->current_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);
} }
#endif /* RPL_LEAF_ONLY */
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -491,10 +542,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;
@ -520,32 +572,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 RPL options present. */ /* Check if there are any RPL options present. */
@ -561,7 +618,7 @@ dao_input(void)
switch(subopt_type) { switch(subopt_type) {
case RPL_OPTION_TARGET: case RPL_OPTION_TARGET:
/* handle the target option */ /* Handle the target option. */
prefixlen = buffer[i + 3]; prefixlen = buffer[i + 3];
memset(&prefix, 0, sizeof(prefix)); memset(&prefix, 0, sizeof(prefix));
memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT); memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT);
@ -577,7 +634,7 @@ dao_input(void)
} }
PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ", PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ",
(unsigned)lifetime, (unsigned)prefixlen); (unsigned)lifetime, (unsigned)prefixlen);
PRINT6ADDR(&prefix); PRINT6ADDR(&prefix);
PRINTF("\n"); PRINTF("\n");
@ -585,7 +642,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");
@ -601,25 +658,25 @@ 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;
} }
} }
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
if(rep == NULL) { if(rep == NULL) {
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); RPL_STAT(rpl_stats.mem_overflows++);
if(rep == NULL) { PRINTF("RPL: Could not add a route after receiving a DAO\n");
RPL_STAT(rpl_stats.mem_overflows++); return;
PRINTF("RPL: Could not add a route after receiving a DAO\n");
return;
}
} }
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) {
@ -629,16 +686,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;
@ -652,7 +711,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;
@ -661,23 +720,32 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
dag = n->dag; dag = n->dag;
} }
instance = dag->instance;
#ifdef RPL_DEBUG_DAO_OUTPUT #ifdef RPL_DEBUG_DAO_OUTPUT
RPL_DEBUG_DAO_OUTPUT(n); RPL_DEBUG_DAO_OUTPUT(n);
#endif #endif
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;
@ -726,9 +794,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];
@ -741,7 +806,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;
@ -751,7 +816,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;

View file

@ -52,13 +52,15 @@
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)
{ {
@ -142,7 +170,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
dag = p1->dag; /* Both parents must be in the same DAG. */ dag = p1->dag; /* Both parents must be in the same DAG. */
min_diff = RPL_DAG_MC_ETX_DIVISOR / min_diff = RPL_DAG_MC_ETX_DIVISOR /
PARENT_SWITCH_THRESHOLD_DIV; PARENT_SWITCH_THRESHOLD_DIV;
p1_metric = calculate_path_metric(p1); p1_metric = calculate_path_metric(p1);
@ -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

View file

@ -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;
} }

View file

@ -94,6 +94,16 @@
#define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */ #define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */
#define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */ #define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* RPL IPv6 extension header option. */
#define RPL_HDR_OPT_LEN 4
#define RPL_HOP_BY_HOP_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
/*---------------------------------------------------------------------------*/
/* Default values for RPL constants and variables. */ /* Default values for RPL constants and variables. */
/* The default value for the DAO timer. */ /* The default value for the DAO timer. */
@ -108,8 +118,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
@ -118,13 +128,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
@ -208,7 +218,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;
@ -241,33 +251,44 @@ 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);
/* 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);
@ -276,8 +297,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. */

View file

@ -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,64 @@ 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)
{ {
/* only reset if not just reset or started */ #if !RPL_LEAF_ONLY
if(force || dag->dio_intcurrent > dag->dio_intmin) { /* Do not reset if we are already on the minimum interval,
dag->dio_counter = 0; unless forced to do so. */
dag->dio_intcurrent = dag->dio_intmin; if(force || instance->dio_intcurrent > instance->dio_intmin) {
new_dio_interval(dag); instance->dio_counter = 0;
instance->dio_intcurrent = instance->dio_intmin;
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);
} }
} }
/************************************************************************/ /************************************************************************/

View file

@ -86,6 +86,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 +124,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 +140,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,66 +150,55 @@ 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;
parent = rpl_find_parent(dag, &ipaddr); if(instance->of->parent_state_callback != NULL) {
if(parent == NULL) { instance->of->parent_state_callback(parent, known, etx);
if(!known) { }
PRINTF("RPL: Deleting routes installed by DAOs received from "); if(!known) {
PRINT6ADDR(&ipaddr); PRINTF("RPL: Removing parent ");
PRINTF("\n"); PRINT6ADDR(&parent->addr);
uip_ds6_route_rm_by_nexthop(&ipaddr); PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx);
parent->rank = INFINITE_RANK;
}
}
} }
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) { if(!known) {
PRINTF("RPL: Removing parent "); PRINTF("RPL: Deleting routes installed by DAOs received from ");
PRINT6ADDR(&parent->addr); PRINT6ADDR(&ipaddr);
PRINTF(" because of bad connectivity (ETX %d)\n", etx); PRINTF("\n");
parent->rank = INFINITE_RANK; uip_ds6_route_rm_by_nexthop(&ipaddr);
} }
} }
/************************************************************************/ /************************************************************************/
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(p != NULL) { if(instance->used == 1 ) {
p->rank = INFINITE_RANK; p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
/* Trigger DAG rank recalculation. */ if(p != NULL) {
p->updated = 1; p->rank = INFINITE_RANK;
/* Trigger DAG rank recalculation. */
p->updated = 1;
}
}
} }
} }
} }
@ -201,6 +208,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);

View file

@ -73,19 +73,77 @@
#endif /* RPL_CONF_OF */ #endif /* RPL_CONF_OF */
/* 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 0x1e
/*
* This value decides if this node must stay as a leaf or not
* 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 */
/* This value is used to access an arbitrary DAG. It will likely be
replaced when we support multiple DAGs more. */
#define RPL_ANY_INSTANCE -1
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* 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)))
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* 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 +197,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 +212,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 +259,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,51 +280,36 @@ 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; rpl_dag_t *current_dag;
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 instance_id; uint8_t instance_id;
uint8_t version; uint8_t used;
uint8_t grounded; uint8_t dtsn_out;
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;
uint8_t default_lifetime;
uint8_t dio_intcurrent;
uint8_t dio_send; /* for keeping track of which mode the timer is in */
uint8_t dio_counter;
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;
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_send; /* for keeping track of which mode the timer is in
*/
uint8_t dio_counter;
#if RPL_CONF_STATS #if RPL_CONF_STATS
uint16_t dio_totint; uint16_t dio_totint;
uint16_t dio_totsend; uint16_t dio_totsend;
@ -241,19 +318,23 @@ 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 *); void uip_rpl_input(void);
int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len); rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id);
int rpl_repair_dag(rpl_dag_t *dag); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len);
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); int rpl_repair_root(uint8_t instance_id);
rpl_dag_t *rpl_get_dag(int instance_id); int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from);
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);
void rpl_update_header_empty(void);
int rpl_update_header_final(uip_ipaddr_t *addr);
int rpl_verify_header(int);
void rpl_remove_header(void);
uint8_t rpl_invert_header(void);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#endif /* RPL_H */ #endif /* RPL_H */

View file

@ -27,10 +27,8 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
*
*
* $Id: tcpip.c,v 1.30 2010/10/29 05:36:07 adamdunkels Exp $
*/ */
/** /**
* \file * \file
* Code for tunnelling uIP packets over the Rime mesh routing module * Code for tunnelling uIP packets over the Rime mesh routing module
@ -39,29 +37,20 @@
* \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code) * \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
* \author Julien Abeille <jabeille@cisco.com> (IPv6 related code) * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
*/ */
#include "contiki-net.h" #include "contiki-net.h"
#include "net/uip-split.h" #include "net/uip-split.h"
#include "net/uip-packetqueue.h" #include "net/uip-packetqueue.h"
#include <string.h>
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
#include "net/uip-nd6.h" #include "net/uip-nd6.h"
#include "net/uip-ds6.h" #include "net/uip-ds6.h"
#endif #endif
#define DEBUG 0 #include <string.h>
#if DEBUG
#include <stdio.h> #define DEBUG DEBUG_NONE
#define PRINTF(...) printf(__VA_ARGS__) #include "net/uip-debug.h"
#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#endif
#if UIP_LOGGING #if UIP_LOGGING
#include <stdio.h> #include <stdio.h>
@ -78,21 +67,21 @@ void uip_log(char *msg);
#ifdef UIP_FALLBACK_INTERFACE #ifdef UIP_FALLBACK_INTERFACE
extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE; extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
#endif #endif
#if UIP_CONF_IPV6_RPL #if UIP_CONF_IPV6_RPL
void rpl_init(void); #include "rpl/rpl.h"
#endif #endif
process_event_t tcpip_event; process_event_t tcpip_event;
#if UIP_CONF_ICMP6 #if UIP_CONF_ICMP6
process_event_t tcpip_icmp6_event; process_event_t tcpip_icmp6_event;
#endif /* UIP_CONF_ICMP6 */ #endif /* UIP_CONF_ICMP6 */
/*static struct tcpip_event_args ev_args;*/ /* Periodic check of active connections. */
/*periodic check of active connections*/
static struct etimer periodic; static struct etimer periodic;
#if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
/*timer for reassembly*/ /* Timer for reassembly. */
extern struct etimer uip_reass_timer; extern struct etimer uip_reass_timer;
#endif #endif
@ -412,21 +401,19 @@ eventhandler(process_event_t ev, process_data_t data)
cptr->appstate.p = PROCESS_NONE; cptr->appstate.p = PROCESS_NONE;
cptr->tcpstateflags = UIP_CLOSED; cptr->tcpstateflags = UIP_CLOSED;
} }
} }
} }
#endif /* UIP_TCP */ #endif /* UIP_TCP */
#if UIP_UDP #if UIP_UDP
{ {
register struct uip_udp_conn *cptr; register struct uip_udp_conn *cptr;
for(cptr = &uip_udp_conns[0]; for(cptr = &uip_udp_conns[0];
cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
if(cptr->appstate.p == p) { if(cptr->appstate.p == p) {
cptr->lport = 0; cptr->lport = 0;
} }
} }
} }
#endif /* UIP_UDP */ #endif /* UIP_UDP */
break; break;
@ -477,12 +464,12 @@ eventhandler(process_event_t ev, process_data_t data)
* check the different timers for neighbor discovery and * check the different timers for neighbor discovery and
* stateless autoconfiguration * stateless autoconfiguration
*/ */
/*if(data == &uip_nd6_timer_periodic && /*if(data == &uip_ds6_timer_periodic &&
etimer_expired(&uip_nd6_timer_periodic)) { etimer_expired(&uip_ds6_timer_periodic)) {
uip_nd6_periodic(); uip_ds6_periodic();
tcpip_ipv6_output(); tcpip_ipv6_output();
}*/ }*/
#if !UIP_CONF_ROUTER #if !UIP_CONF_ROUTER
if(data == &uip_ds6_timer_rs && if(data == &uip_ds6_timer_rs &&
etimer_expired(&uip_ds6_timer_rs)){ etimer_expired(&uip_ds6_timer_rs)){
uip_ds6_send_rs(); uip_ds6_send_rs();
@ -551,22 +538,24 @@ void
tcpip_ipv6_output(void) tcpip_ipv6_output(void)
{ {
uip_ds6_nbr_t *nbr = NULL; uip_ds6_nbr_t *nbr = NULL;
uip_ipaddr_t* nexthop; uip_ipaddr_t *nexthop;
if(uip_len == 0) { if(uip_len == 0) {
return; return;
} }
if(uip_len > UIP_LINK_MTU) { if(uip_len > UIP_LINK_MTU) {
UIP_LOG("tcpip_ipv6_output: Packet to big"); UIP_LOG("tcpip_ipv6_output: Packet to big");
uip_len = 0; uip_len = 0;
return; return;
} }
if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
uip_len = 0; uip_len = 0;
return; return;
} }
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
/* Next hop determination */ /* Next hop determination */
nbr = NULL; nbr = NULL;
@ -578,10 +567,18 @@ tcpip_ipv6_output(void)
if(locrt == NULL) { if(locrt == NULL) {
if((nexthop = uip_ds6_defrt_choose()) == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) {
#ifdef UIP_FALLBACK_INTERFACE #ifdef UIP_FALLBACK_INTERFACE
printf("FALLBACK: removing ext hdrs & setting proto %d %d\n",
uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
if(uip_ext_len > 0) {
uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
remove_ext_hdr();
/* This should be copied from the ext header... */
UIP_IP_BUF->proto = proto;
}
UIP_FALLBACK_INTERFACE.output(); UIP_FALLBACK_INTERFACE.output();
#else #else
PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif #endif /* !UIP_FALLBACK_INTERFACE */
uip_len = 0; uip_len = 0;
return; return;
} }
@ -589,16 +586,20 @@ tcpip_ipv6_output(void)
nexthop = &locrt->nexthop; nexthop = &locrt->nexthop;
} }
} }
/* end of next hop determination */ /* End of next hop determination */
#if UIP_CONF_IPV6_RPL
if(rpl_update_header_final(nexthop)) {
uip_len = 0;
return;
}
#endif /* UIP_CONF_IPV6_RPL */
if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
// printf("add1 %d\n", nexthop->u8[15]);
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
// printf("add n\n");
uip_len = 0; uip_len = 0;
return; return;
} else { } else {
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* copy outgoing pkt in the queuing buffer for later transmmit */ /* Copy outgoing pkt in the queuing buffer for later transmit. */
if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
@ -616,59 +617,47 @@ tcpip_ipv6_output(void)
uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
} }
stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
nbr->nscount = 1; nbr->nscount = 1;
} }
} else { } else {
if(nbr->state == NBR_INCOMPLETE) { if(nbr->state == NBR_INCOMPLETE) {
PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* copy outgoing pkt in the queuing buffer for later transmmit and set /* Copy outgoing pkt in the queuing buffer for later transmit and set
the destination nbr to nbr */ the destination nbr to nbr. */
if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
} }
/* memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len);
nbr->queue_buf_len = uip_len;*/
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
uip_len = 0; uip_len = 0;
return; return;
} }
/* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep /* Send in parallel if we are running NUD (nbc state is either STALE,
sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */
if(nbr->state == NBR_STALE) { if(nbr->state == NBR_STALE) {
nbr->state = NBR_DELAY; nbr->state = NBR_DELAY;
stimer_set(&(nbr->reachable), stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
UIP_ND6_DELAY_FIRST_PROBE_TIME);
nbr->nscount = 0; nbr->nscount = 0;
PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
} }
stimer_set(&(nbr->sendns),
uip_ds6_if.retrans_timer / 1000);
tcpip_output(&(nbr->lladdr));
stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
tcpip_output(&nbr->lladdr);
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* Send the queued packets from here, may not be 100% perfect though. /*
* Send the queued packets from here, may not be 100% perfect though.
* This happens in a few cases, for example when instead of receiving a * This happens in a few cases, for example when instead of receiving a
* NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
*to STALE, and you must both send a NA and the queued packet * to STALE, and you must both send a NA and the queued packet.
*/ */
/* if(nbr->queue_buf_len != 0) {
uip_len = nbr->queue_buf_len;
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
nbr->queue_buf_len = 0;
tcpip_output(&(nbr->lladdr));
}*/
if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
uip_len = uip_packetqueue_buflen(&nbr->packethandle); uip_len = uip_packetqueue_buflen(&nbr->packethandle);
memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
uip_packetqueue_free(&nbr->packethandle); uip_packetqueue_free(&nbr->packethandle);
tcpip_output(&(nbr->lladdr)); tcpip_output(&nbr->lladdr);
} }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
@ -676,14 +665,13 @@ tcpip_ipv6_output(void)
return; return;
} }
} }
/*multicast IP destination address */ /* Multicast IP destination address. */
tcpip_output(NULL); tcpip_output(NULL);
uip_len = 0; uip_len = 0;
uip_ext_len = 0; uip_ext_len = 0;
} }
#endif #endif /* UIP_CONF_IPV6 */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_UDP #if UIP_UDP
void void

View file

@ -5,9 +5,9 @@
/** /**
* \file * \file
* IPv6 data structures handling functions * IPv6 data structures handling functions.
* Comprises part of the Neighbor discovery (RFC 4861) * Comprises part of the Neighbor discovery (RFC 4861)
* and auto configuration (RFC 4862 )state machines * and auto configuration (RFC 4862) state machines.
* \author Mathilde Durvy <mdurvy@cisco.com> * \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com> * \author Julien Abeille <jabeille@cisco.com>
*/ */
@ -148,16 +148,19 @@ uip_ds6_init(void)
void void
uip_ds6_periodic(void) uip_ds6_periodic(void)
{ {
/* Periodic processing on unicast addresses */ /* Periodic processing on unicast addresses */
for(locaddr = uip_ds6_if.addr_list; for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if(locaddr->isused) { if(locaddr->isused) {
if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
uip_ds6_addr_rm(locaddr); uip_ds6_addr_rm(locaddr);
#if UIP_ND6_DEF_MAXDADNS > 0
} else if((locaddr->state == ADDR_TENTATIVE) } else if((locaddr->state == ADDR_TENTATIVE)
&& (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
&& (timer_expired(&locaddr->dadtimer))) { && (timer_expired(&locaddr->dadtimer))) {
uip_ds6_dad(locaddr); uip_ds6_dad(locaddr);
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
} }
} }
} }
@ -366,6 +369,24 @@ uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr)
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr)
{
uip_ds6_nbr_t *fin;
for(locnbr = uip_ds6_nbr_cache, fin = locnbr + UIP_DS6_NBR_NB;
locnbr < fin;
++locnbr) {
if(locnbr->isused) {
if(!memcmp(lladdr, &locnbr->lladdr, UIP_LLADDR_LEN)) {
return locnbr;
}
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_defrt_t * uip_ds6_defrt_t *
uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
@ -549,7 +570,6 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
(uip_ds6_element_t **)&locaddr) == FREESPACE) { (uip_ds6_element_t **)&locaddr) == FREESPACE) {
locaddr->isused = 1; locaddr->isused = 1;
uip_ipaddr_copy(&locaddr->ipaddr, ipaddr); uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
locaddr->state = ADDR_TENTATIVE;
locaddr->type = type; locaddr->type = type;
if(vlifetime == 0) { if(vlifetime == 0) {
locaddr->isinfinite = 1; locaddr->isinfinite = 1;
@ -557,10 +577,15 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
locaddr->isinfinite = 0; locaddr->isinfinite = 0;
stimer_set(&(locaddr->vlifetime), vlifetime); stimer_set(&(locaddr->vlifetime), vlifetime);
} }
#if UIP_ND6_DEF_MAXDADNS > 0
locaddr->state = ADDR_TENTATIVE;
timer_set(&locaddr->dadtimer, timer_set(&locaddr->dadtimer,
random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
CLOCK_SECOND)); CLOCK_SECOND));
locaddr->dadnscount = 0; locaddr->dadnscount = 0;
#else /* UIP_ND6_DEF_MAXDADNS > 0 */
locaddr->state = ADDR_PREFERRED;
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
uip_create_solicited_node(ipaddr, &loc_fipaddr); uip_create_solicited_node(ipaddr, &loc_fipaddr);
uip_ds6_maddr_add(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr);
return locaddr; return locaddr;
@ -759,6 +784,10 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop,
uip_ipaddr_copy(&(locroute->nexthop), nexthop); uip_ipaddr_copy(&(locroute->nexthop), nexthop);
locroute->metric = metric; locroute->metric = metric;
#ifdef UIP_DS6_ROUTE_STATE_TYPE
memset(&locroute->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
#endif
PRINTF("DS6: adding route: "); PRINTF("DS6: adding route: ");
PRINT6ADDR(ipaddr); PRINT6ADDR(ipaddr);
PRINTF(" via "); PRINTF(" via ");
@ -884,6 +913,7 @@ get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_ND6_DEF_MAXDADNS > 0
void void
uip_ds6_dad(uip_ds6_addr_t *addr) uip_ds6_dad(uip_ds6_addr_t *addr)
{ {
@ -922,10 +952,11 @@ uip_ds6_dad_failed(uip_ds6_addr_t * addr)
uip_ds6_addr_rm(addr); uip_ds6_addr_rm(addr);
return 1; return 1;
} }
#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
/*---------------------------------------------------------------------------*/
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
/*---------------------------------------------------------------------------*/
void void
uip_ds6_send_ra_sollicited(void) uip_ds6_send_ra_sollicited(void)
{ {

View file

@ -124,6 +124,13 @@
#endif #endif
#define UIP_DS6_AADDR_NB UIP_DS6_AADDR_NBS + UIP_DS6_AADDR_NBU #define UIP_DS6_AADDR_NB UIP_DS6_AADDR_NBS + UIP_DS6_AADDR_NBU
/*--------------------------------------------------*/
/* Should we use LinkLayer acks in NUD ?*/
#ifndef UIP_CONF_DS6_LL_NUD
#define UIP_DS6_LL_NUD 0
#else
#define UIP_DS6_LL_NUD UIP_CONF_DS6_LL_NUD
#endif
/*--------------------------------------------------*/ /*--------------------------------------------------*/
/** \brief Possible states for the nbr cache entries */ /** \brief Possible states for the nbr cache entries */
@ -209,8 +216,10 @@ typedef struct uip_ds6_addr {
uint8_t type; uint8_t type;
uint8_t isinfinite; uint8_t isinfinite;
struct stimer vlifetime; struct stimer vlifetime;
#if UIP_ND6_DEF_MAXDADNS > 0
struct timer dadtimer; struct timer dadtimer;
uint8_t dadnscount; uint8_t dadnscount;
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
} uip_ds6_addr_t; } uip_ds6_addr_t;
/** \brief Anycast address */ /** \brief Anycast address */
@ -310,6 +319,7 @@ uip_ds6_nbr_t *uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr,
uint8_t isrouter, uint8_t state); uint8_t isrouter, uint8_t state);
void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr);
uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr);
uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr);
/** @} */ /** @} */
@ -385,11 +395,13 @@ void uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr);
/** \brief Get the number of matching bits of two addresses */ /** \brief Get the number of matching bits of two addresses */
uint8_t get_match_length(uip_ipaddr_t * src, uip_ipaddr_t * dst); uint8_t get_match_length(uip_ipaddr_t * src, uip_ipaddr_t * dst);
#if UIP_ND6_DEF_MAXDADNS >0
/** \brief Perform Duplicate Address Selection on one address */ /** \brief Perform Duplicate Address Selection on one address */
void uip_ds6_dad(uip_ds6_addr_t * ifaddr); void uip_ds6_dad(uip_ds6_addr_t * ifaddr);
/** \brief Callback when DAD failed */ /** \brief Callback when DAD failed */
int uip_ds6_dad_failed(uip_ds6_addr_t * ifaddr); int uip_ds6_dad_failed(uip_ds6_addr_t * ifaddr);
#endif /* UIP_ND6_DEF_MAXDADNS */
/** \brief Source address selection, see RFC 3484 */ /** \brief Source address selection, see RFC 3484 */
void uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst); void uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst);

View file

@ -60,14 +60,25 @@
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
#define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
#if UIP_CONF_IPV6_RPL
#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
#define UIP_FIRST_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN])
#endif /* UIP_CONF_IPV6_RPL */
/** \brief temporary IP address */ /** \brief temporary IP address */
static uip_ipaddr_t tmp_ipaddr; static uip_ipaddr_t tmp_ipaddr;
#if UIP_CONF_IPV6_RPL
#include "rpl/rpl.h"
#endif /* UIP_CONF_IPV6_RPL */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_icmp6_echo_request_input(void) uip_icmp6_echo_request_input(void)
{ {
#if UIP_CONF_IPV6_RPL
u8_t temp_ext_len;
#endif /* UIP_CONF_IPV6_RPL */
/* /*
* we send an echo reply. It is trivial if there was no extension * we send an echo reply. It is trivial if there was no extension
* headers in the request otherwise we need to remove the extension * headers in the request otherwise we need to remove the extension
@ -78,7 +89,7 @@ uip_icmp6_echo_request_input(void)
PRINTF("to"); PRINTF("to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n"); PRINTF("\n");
/* IP header */ /* IP header */
UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
@ -92,30 +103,54 @@ uip_icmp6_echo_request_input(void)
} }
if(uip_ext_len > 0) { if(uip_ext_len > 0) {
/* If there were extension headers*/ #if UIP_CONF_IPV6_RPL
UIP_IP_BUF->proto = UIP_PROTO_ICMP6; if ((temp_ext_len=rpl_invert_header())) {
uip_len -= uip_ext_len; /* If there were other extension headers*/
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6;
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); if (uip_ext_len != temp_ext_len) {
/* move the echo request payload (starting after the icmp header) uip_len -= (uip_ext_len - temp_ext_len);
* to the new location in the reply. UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
* The shift is equal to the length of the extension headers present UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
* Note: UIP_ICMP_BUF still points to the echo request at this stage /* move the echo request payload (starting after the icmp header)
*/ * to the new location in the reply.
memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, * The shift is equal to the length of the remaining extension headers present
(uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, * Note: UIP_ICMP_BUF still points to the echo request at this stage
(uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); */
memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len),
(uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
(uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN));
}
uip_ext_len=temp_ext_len;
} else {
#endif /* UIP_CONF_IPV6_RPL */
/* If there were extension headers*/
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
uip_len -= uip_ext_len;
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
/* move the echo request payload (starting after the icmp header)
* to the new location in the reply.
* The shift is equal to the length of the extension headers present
* Note: UIP_ICMP_BUF still points to the echo request at this stage
*/
memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len,
(uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
(uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN));
uip_ext_len = 0;
#if UIP_CONF_IPV6_RPL
}
#endif /* UIP_CONF_IPV6_RPL */
} }
/* Below is important for the correctness of UIP_ICMP_BUF and the /* Below is important for the correctness of UIP_ICMP_BUF and the
* checksum * checksum
*/ */
uip_ext_len = 0;
/* Note: now UIP_ICMP_BUF points to the beginning of the echo reply */ /* Note: now UIP_ICMP_BUF points to the beginning of the echo reply */
UIP_ICMP_BUF->type = ICMP6_ECHO_REPLY; UIP_ICMP_BUF->type = ICMP6_ECHO_REPLY;
UIP_ICMP_BUF->icode = 0; UIP_ICMP_BUF->icode = 0;
UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
PRINTF("Sending Echo Reply to"); PRINTF("Sending Echo Reply to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from"); PRINTF("from");
@ -127,29 +162,45 @@ uip_icmp6_echo_request_input(void)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
uip_ext_len = 0;
/* check if originating packet is not an ICMP error*/ /* check if originating packet is not an ICMP error*/
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ if (uip_ext_len) {
uip_len = 0; if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
return; uip_len = 0;
return;
}
} else {
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
uip_len = 0;
return;
}
} }
/* remember data of original packet before shifting */ #if UIP_CONF_IPV6_RPL
uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); uip_ext_len = rpl_invert_header();
#else /* UIP_CONF_IPV6_RPL */
uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; uip_ext_len = 0;
#endif /* UIP_CONF_IPV6_RPL */
if(uip_len > UIP_LINK_MTU)
uip_len = UIP_LINK_MTU;
memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + UIP_ICMP6_ERROR_LEN, /* remember data of original packet before shifting */
(void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - UIP_ICMP6_ERROR_LEN); uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr);
uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN;
if(uip_len > UIP_LINK_MTU)
uip_len = UIP_LINK_MTU;
memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + uip_ext_len + UIP_ICMP6_ERROR_LEN,
(void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - uip_ext_len - UIP_ICMP6_ERROR_LEN);
UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->tcflow = 0;
UIP_IP_BUF->flow = 0; UIP_IP_BUF->flow = 0;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6; if (uip_ext_len) {
UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6;
} else {
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
}
UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
/* the source should not be unspecified nor multicast, the check for /* the source should not be unspecified nor multicast, the check for
@ -158,7 +209,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
uip_len = 0; uip_len = 0;
return; return;
} }
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
if(uip_is_addr_mcast(&tmp_ipaddr)){ if(uip_is_addr_mcast(&tmp_ipaddr)){
@ -176,7 +227,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
#endif #endif
} }
UIP_ICMP_BUF->type = type; UIP_ICMP_BUF->type = type;
UIP_ICMP_BUF->icode = code; UIP_ICMP_BUF->icode = code;
UIP_ICMP6_ERROR_BUF->param = uip_htonl(param); UIP_ICMP6_ERROR_BUF->param = uip_htonl(param);

View file

@ -76,16 +76,7 @@
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
#define DEBUG 0 #define DEBUG 0
#if DEBUG #include "net/uip-debug.h"
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
#if UIP_LOGGING #if UIP_LOGGING
#include <stdio.h> #include <stdio.h>
@ -154,11 +145,11 @@ create_llao(uint8_t *llao, uint8_t type) {
void void
uip_nd6_ns_input(void) uip_nd6_ns_input(void)
{ {
PRINTF("Received NS from"); PRINTF("Received NS from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to"); PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("with target address"); PRINTF(" with target address");
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
PRINTF("\n"); PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv); UIP_STAT(++uip_stat.nd6.recv);
@ -224,6 +215,7 @@ uip_nd6_ns_input(void)
addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr); addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
if(addr != NULL) { if(addr != NULL) {
#if UIP_ND6_DEF_MAXDADNS > 0
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
/* DAD CASE */ /* DAD CASE */
#if UIP_CONF_IPV6_CHECKS #if UIP_CONF_IPV6_CHECKS
@ -242,6 +234,11 @@ uip_nd6_ns_input(void)
uip_ds6_dad_failed(addr); uip_ds6_dad_failed(addr);
goto discard; goto discard;
} }
#else /* UIP_ND6_DEF_MAXDADNS > 0 */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
/* DAD CASE */
goto discard;
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
} }
#if UIP_CONF_IPV6_CHECKS #if UIP_CONF_IPV6_CHECKS
if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
@ -307,11 +304,11 @@ create_na:
UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
UIP_STAT(++uip_stat.nd6.sent); UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending NA to"); PRINTF("Sending NA to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from"); PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("with target address"); PRINTF(" with target address ");
PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
PRINTF("\n"); PRINTF("\n");
return; return;
@ -441,9 +438,11 @@ uip_nd6_na_input(void)
addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
/* Message processing, including TLLAO if any */ /* Message processing, including TLLAO if any */
if(addr != NULL) { if(addr != NULL) {
#if UIP_ND6_DEF_MAXDADNS > 0
if(addr->state == ADDR_TENTATIVE) { if(addr->state == ADDR_TENTATIVE) {
uip_ds6_dad_failed(addr); uip_ds6_dad_failed(addr);
} }
#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
PRINTF("NA received is bad\n"); PRINTF("NA received is bad\n");
goto discard; goto discard;
} else { } else {

View file

@ -48,8 +48,8 @@
#include "net/uip.h" #include "net/uip.h"
#include "sys/stimer.h" #include "sys/stimer.h"
/** /**
* \name General * \name General
* @{ * @{
*/ */
/** \brief HOP LIMIT to be used when sending ND messages (255) */ /** \brief HOP LIMIT to be used when sending ND messages (255) */
#define UIP_ND6_HOP_LIMIT 255 #define UIP_ND6_HOP_LIMIT 255
@ -57,29 +57,21 @@
#define UIP_ND6_INFINITE_LIFETIME 0xFFFFFFFF #define UIP_ND6_INFINITE_LIFETIME 0xFFFFFFFF
/** @} */ /** @} */
#ifndef UIP_CONF_ND6_DEF_MAXDADNS
/** \brief Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8.2 */
#if UIP_CONF_LL_802154
#define UIP_ND6_DEF_MAXDADNS 0
#else /* UIP_CONF_LL_802154 */
#define UIP_ND6_DEF_MAXDADNS 1 #define UIP_ND6_DEF_MAXDADNS 1
#endif /* UIP_CONF_LL_802154 */
/** \name Configuration options */ #else /* UIP_CONF_ND6_DEF_MAXDADNS */
/** @{ */ #define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS #endif /* UIP_CONF_ND6_DEF_MAXDADNS */
/** \brief max number of entries in the neighbor cache */
#define UIP_CONF_ND6_MAX_NEIGHBORS 4
#endif /*UIP_CONF_ND6_MAX_NEIGHBORS*/
#ifndef UIP_CONF_ND6_MAX_DEFROUTERS
/** \brief max number of entries in the default router cache */
#define UIP_CONF_ND6_MAX_DEFROUTERS 2
#endif /*UIP_CONF_ND6_MAX_DEFROUTERS*/
#ifndef UIP_CONF_ND6_MAX_PREFIXES
/** \brief max number of entries in the prefix list */
#define UIP_CONF_ND6_MAX_PREFIXES 2
#endif /*UIP_CONF_ND6_MAX_PREFIXES*/
/** @} */
/** \name RFC 4861 Host constant */ /** \name RFC 4861 Host constant */
/** @{ */ /** @{ */
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1 #define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4 #define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3 #define UIP_ND6_MAX_RTR_SOLICITATIONS 3
/** @} */ /** @} */
@ -115,7 +107,7 @@
#ifdef UIP_CONF_ND6_RETRANS_TIMER #ifdef UIP_CONF_ND6_RETRANS_TIMER
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER #define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
#else #else
#define UIP_ND6_RETRANS_TIMER 1000 #define UIP_ND6_RETRANS_TIMER 1000
#endif #endif
#define UIP_ND6_DELAY_FIRST_PROBE_TIME 5 #define UIP_ND6_DELAY_FIRST_PROBE_TIME 5
#define UIP_ND6_MIN_RANDOM_FACTOR(x) (x / 2) #define UIP_ND6_MIN_RANDOM_FACTOR(x) (x / 2)
@ -140,8 +132,8 @@
/** \name ND6 message length (excluding options) */ /** \name ND6 message length (excluding options) */
/** @{ */ /** @{ */
#define UIP_ND6_NA_LEN 20 #define UIP_ND6_NA_LEN 20
#define UIP_ND6_NS_LEN 20 #define UIP_ND6_NS_LEN 20
#define UIP_ND6_RA_LEN 12 #define UIP_ND6_RA_LEN 12
#define UIP_ND6_RS_LEN 4 #define UIP_ND6_RS_LEN 4
/** @} */ /** @} */
@ -160,7 +152,7 @@
#define UIP_ND6_OPT_SHORT_LLAO_LEN 8 #define UIP_ND6_OPT_SHORT_LLAO_LEN 8
#define UIP_ND6_OPT_LONG_LLAO_LEN 16 #define UIP_ND6_OPT_LONG_LLAO_LEN 16
/** \brief length of a ND6 LLAO option for 802.15.4 */ /** \brief length of a ND6 LLAO option for 802.15.4 */
#define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN #define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN
#else /*UIP_CONF_LL_802154*/ #else /*UIP_CONF_LL_802154*/
#if UIP_CONF_LL_80211 #if UIP_CONF_LL_80211
/* If the interface is 802.11 */ /* If the interface is 802.11 */
@ -179,93 +171,18 @@
#define UIP_ND6_NA_FLAG_ROUTER 0x80 #define UIP_ND6_NA_FLAG_ROUTER 0x80
#define UIP_ND6_NA_FLAG_SOLICITED 0x40 #define UIP_ND6_NA_FLAG_SOLICITED 0x40
#define UIP_ND6_NA_FLAG_OVERRIDE 0x20 #define UIP_ND6_NA_FLAG_OVERRIDE 0x20
#define UIP_ND6_RA_FLAG_ONLINK 0x80 #define UIP_ND6_RA_FLAG_ONLINK 0x80
#define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40 #define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40
/** @} */ /** @} */
/**
* \brief Possible states for the neighbor cache entries
*
* NO_STATE is for implementation purposes: a router entry contains a pointer
* to a neighbor entry, which holds its ip address. If we do not know the LL
* address of the router, we do not have to create a neighbor entry as per
* RFC 4861. However, we still need to have the IP of the router stored in a
* neighbor entry, hence we create an entry in the NO_STATE state
*/
typedef enum {
INCOMPLETE = 0,
REACHABLE = 1,
STALE = 2,
DELAY = 3,
PROBE = 4,
NO_STATE = 5
} uip_neighbor_state;
/**
* \name ND structures
* @{
*/
/** \brief An entry in the neighbor cache */
struct uip_nd6_neighbor {
uip_ipaddr_t ipaddr;
uip_lladdr_t lladdr;
u8_t isrouter;
uip_neighbor_state state;
struct stimer reachable;
struct stimer last_send; /**< last time a ND message was sent */
u8_t count_send; /**< how many ND message were already sent */
u8_t used; /**< brief is this neighbor currently used */
#if UIP_CONF_IPV6_QUEUE_PKT
u8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
/**< buffer to hold one packet during address resolution */
u8_t queue_buf_len;
/**< length of the pkt in buffer, used as "boolean" as well*/
#endif /*UIP_CONF_QUEUE_PKT*/
};
/** \brief An entry in the default router list */
struct uip_nd6_defrouter {
struct uip_nd6_neighbor *nb;
struct stimer lifetime;
/**< the lifetime contained in RA corresponds to the interval field
* of the timer
*/
u8_t used; /**< Is this default router entry currently used */
};
/** \brief A prefix list entry */
struct uip_nd6_prefix {
uip_ipaddr_t ipaddr;
u8_t length;
/**< we do not use preferred lifetime, which is always smaller than
* valid lifetime (for addr, preferred->deprecated)
*/
struct stimer vlifetime;
u8_t is_infinite; /**< Is the prefix lifetime INFINITE */
u8_t used; /**< Is this prefix entry currently used */
};
/** @} */
extern struct etimer uip_nd6_timer_periodic;
/**
* \note
* We do not use a destination cache, do next-hop determination each time
* a packet needs to be sent. (info such as rtt, path mtu could be stored
* in uip_conn)
*
*/
/** /**
* \name ND message structures * \name ND message structures
* @{ * @{
*/ */
/** /**
* \brief A neighbor solicitation constant part * \brief A neighbor solicitation constant part
* *
* Possible option is: SLLAO * Possible option is: SLLAO
*/ */
typedef struct uip_nd6_ns { typedef struct uip_nd6_ns {
@ -275,19 +192,19 @@ typedef struct uip_nd6_ns {
/** /**
* \brief A neighbor advertisement constant part. * \brief A neighbor advertisement constant part.
* *
* Possible option is: TLLAO * Possible option is: TLLAO
*/ */
typedef struct uip_nd6_na { typedef struct uip_nd6_na {
uint8_t flagsreserved; uint8_t flagsreserved;
uint8_t reserved[3]; uint8_t reserved[3];
uip_ipaddr_t tgtipaddr; uip_ipaddr_t tgtipaddr;
} uip_nd6_na; } uip_nd6_na;
/** /**
* \brief A router solicitation constant part * \brief A router solicitation constant part
* *
* Possible option is: SLLAO * Possible option is: SLLAO
*/ */
typedef struct uip_nd6_rs { typedef struct uip_nd6_rs {
uint32_t reserved; uint32_t reserved;
@ -295,7 +212,7 @@ typedef struct uip_nd6_rs {
/** /**
* \brief A router advertisement constant part * \brief A router advertisement constant part
* *
* Possible options are: SLLAO, MTU, Prefix Information * Possible options are: SLLAO, MTU, Prefix Information
*/ */
typedef struct uip_nd6_ra { typedef struct uip_nd6_ra {
@ -308,13 +225,13 @@ typedef struct uip_nd6_ra {
/** /**
* \brief A redirect message constant part * \brief A redirect message constant part
* *
* Possible options are: TLLAO, redirected header * Possible options are: TLLAO, redirected header
*/ */
typedef struct uip_nd6_redirect { typedef struct uip_nd6_redirect {
uint32_t reserved; uint32_t reserved;
uip_ipaddr_t tgtipaddress; uip_ipaddr_t tgtipaddress;
uip_ipaddr_t destipaddress; uip_ipaddr_t destipaddress;
} uip_nd6_redirect; } uip_nd6_redirect;
/** @} */ /** @} */
@ -357,102 +274,6 @@ typedef struct uip_nd6_opt_redirected_hdr {
} uip_nd6_opt_redirected_hdr; } uip_nd6_opt_redirected_hdr;
/** @} */ /** @} */
/**
* \name ND Neighbor Cache, Router List and Prefix List handling functions
* @{
*/
/**
* \brief Initialize Neighbor Discovery structures
*/
void uip_nd6_init(void);
/**
* \brief Periodic processing of Neighbor Discovery Structures
*/
void uip_nd6_periodic(void);
/**
* \brief Look for a neighbor cache entry corresponding to a specific IP
* address
* \param ipaddr the specific IP address
* \return the corresponding neighbor cache entry
*/
struct uip_nd6_neighbor *uip_nd6_nbrcache_lookup(uip_ipaddr_t *ipaddr);
/**
* \brief Add a neighbor cache entry
* \param ipaddr the IP address of the entry
* \param lladdr the layer 2 address of the entry
* \param isrouter true is the entry is a router
* \param state the state of the entry
* \return the new neighbor or updated cache entry
*/
struct uip_nd6_neighbor * uip_nd6_nbrcache_add(uip_ipaddr_t *ipaddr,
uip_lladdr_t *lladdr,
u8_t isrouter,
uip_neighbor_state state);
/**
* \brief Returns a default router
*/
struct uip_nd6_defrouter * uip_nd6_choose_defrouter(void);
/**
* \brief Find a default router corresponding to a given neighbor cache entry
* \param neighbor the neighbor cache entry
* \return the corresponding router if any
*/
struct uip_nd6_defrouter *
uip_nd6_defrouter_lookup(struct uip_nd6_neighbor *neighbor);
/**
* \brief Remove a default router
* \param router to be removed
*/
void uip_nd6_defrouter_rm(struct uip_nd6_defrouter *router);
/**
* \brief Add a default router
* \param neighbor the corresponding neighbor cache entry
* \param interval the lifetime of the router
* \return the new or updated defrouter entry
*/
struct uip_nd6_defrouter *
uip_nd6_defrouter_add(struct uip_nd6_neighbor *neighbor, unsigned long interval);
/**
* \brief Check if an IP address in on-link by looking at prefix list
* \param ipaddr an IP address
* \return true if on-link
*/
u8_t uip_nd6_is_addr_onlink(uip_ipaddr_t *ipaddr);
/**
* \brief Find a given prefix
* \param ipaddr an IP address
* \return the corresponding prefix if any
*/
struct uip_nd6_prefix *
uip_nd6_prefix_lookup(uip_ipaddr_t *ipaddr);
/**
* \brief Add a prefix
* \param ipaddr the IP address of the prefix
* \param length the length of the prefix
* \param interval the lifetime of the prefix
* \return the new or updated prefix entry
*/
struct uip_nd6_prefix *
uip_nd6_prefix_add(uip_ipaddr_t *ipaddr, u8_t length, unsigned long interval);
/**
* \brief Remove a prefix from th eprefix list
* \param prefix pointer to the prefix to be removed
*/
void
uip_nd6_prefix_rm(struct uip_nd6_prefix *prefix);
/** @} */
/** /**
* \name ND Messages Processing and Generation * \name ND Messages Processing and Generation
* @{ * @{
@ -467,7 +288,7 @@ void
* address) * address)
* *
* We do: * We do:
* - if the tgt belongs to me, reply, otherwise ignore * - if the tgt belongs to me, reply, otherwise ignore
* - if i was performing DAD for the same address, two cases: * - if i was performing DAD for the same address, two cases:
* -- I already sent a NS, hence I win * -- I already sent a NS, hence I win
* -- I did not send a NS yet, hence I lose * -- I did not send a NS yet, hence I lose
@ -476,13 +297,13 @@ void
* address resolution, or DAD and there is a conflict), we do it in this * address resolution, or DAD and there is a conflict), we do it in this
* function: set src, dst, tgt address in the three cases, then for all cases * function: set src, dst, tgt address in the three cases, then for all cases
* set the rest, including SLLAO * set the rest, including SLLAO
* *
*/ */
void void
uip_nd6_ns_input(void); uip_nd6_ns_input(void);
/** /**
* \brief Send a neighbor solicitation, send a Neighbor Advertisement * \brief Send a neighbor solicitation, send a Neighbor Advertisement
* \param src pointer to the src of the NS if known * \param src pointer to the src of the NS if known
* \param dest pointer to ip address to send the NS, for DAD or ADDR Resol, * \param dest pointer to ip address to send the NS, for DAD or ADDR Resol,
* MUST be NULL, for NUD, must be correct unicast dest * MUST be NULL, for NUD, must be correct unicast dest
@ -496,13 +317,13 @@ uip_nd6_ns_input(void);
* solicitation. Otherwise, any one of the addresses assigned to the * solicitation. Otherwise, any one of the addresses assigned to the
* interface should be used." * interface should be used."
* This is why we have a src ip address as argument. If NULL, we will do * This is why we have a src ip address as argument. If NULL, we will do
* src address selection, otherwise we use the argument. * src address selection, otherwise we use the argument.
* *
* - we check if it is a NS for Address resolution or NUD, if yes we include * - we check if it is a NS for Address resolution or NUD, if yes we include
* a SLLAO option, otherwise no. * a SLLAO option, otherwise no.
*/ */
void void
uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt); uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt);
/** /**
* \brief Process a Neighbor Advertisement * \brief Process a Neighbor Advertisement
@ -528,7 +349,7 @@ uip_nd6_na_input(void);
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
/** /**
* \brief Process a Router Solicitation * \brief Process a Router Solicitation
* *
*/ */
void uip_nd6_rs_input(void); void uip_nd6_rs_input(void);
@ -543,12 +364,12 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest);
/** /**
* \brief Send a Router Solicitation * \brief Send a Router Solicitation
* *
* src is chosen through the uip_netif_select_src function. If src is * src is chosen through the uip_netif_select_src function. If src is
* unspecified (i.e. we do not have a preferred address yet), then we do not * unspecified (i.e. we do not have a preferred address yet), then we do not
* put a SLLAO option (MUST NOT in RFC 4861). Otherwise we do. * put a SLLAO option (MUST NOT in RFC 4861). Otherwise we do.
* *
* RS message format, * RS message format,
* possible option is SLLAO, MUST NOT be included if source = unspecified * possible option is SLLAO, MUST NOT be included if source = unspecified
* SHOULD be included otherwise * SHOULD be included otherwise
*/ */
@ -559,7 +380,7 @@ void uip_nd6_rs_output(void);
* \brief process a Router Advertisement * \brief process a Router Advertisement
* *
* - Possible actions when receiving a RA: add router to router list, * - Possible actions when receiving a RA: add router to router list,
* recalculate reachable time, update link hop limit, update retrans timer. * recalculate reachable time, update link hop limit, update retrans timer.
* - If MTU option: update MTU. * - If MTU option: update MTU.
* - If SLLAO option: update entry in neighbor cache * - If SLLAO option: update entry in neighbor cache
* - If prefix option: start autoconf, add prefix to prefix list * - If prefix option: start autoconf, add prefix to prefix list
@ -570,13 +391,13 @@ uip_nd6_ra_input(void);
void void
uip_appserver_addr_get(uip_ipaddr_t *ipaddr); uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
/*--------------------------------------*/ /*--------------------------------------*/
/******* ANNEX - message formats ********/ /******* ANNEX - message formats ********/
/*--------------------------------------*/ /*--------------------------------------*/
/* /*
* RS format. possible option is SLLAO * RS format. possible option is SLLAO
* 0 1 2 3 * 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -644,7 +465,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
* | Options ... * | Options ...
* +-+-+-+-+-+-+-+-+-+-+-+- * +-+-+-+-+-+-+-+-+-+-+-+-
* *
* *
* Redirect message format. Possible options are TLLAO and Redirected header * Redirect message format. Possible options are TLLAO and Redirected header
* *
* 0 1 2 3 * 0 1 2 3
@ -673,7 +494,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
* | Options ... * | Options ...
* +-+-+-+-+-+-+-+-+-+-+-+- * +-+-+-+-+-+-+-+-+-+-+-+-
* *
* *
* SLLAO/TLLAO option: * SLLAO/TLLAO option:
* 0 1 2 3 * 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -681,7 +502,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
* | Type | Length | Link-Layer Address ... * | Type | Length | Link-Layer Address ...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* *
* *
* Prefix information option * Prefix information option
* 0 1 2 3 * 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -712,8 +533,8 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MTU | * | MTU |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* *
* *
* Redirected header option * Redirected header option
* *
* 0 1 2 3 * 0 1 2 3
@ -728,7 +549,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
* | | * | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* *
*/ */
#endif /* __UIP_ND6_H__ */ #endif /* __UIP_ND6_H__ */
/** @} */ /** @} */

View file

@ -1770,6 +1770,17 @@ typedef struct uip_ext_hdr_opt_padn {
u8_t opt_len; u8_t opt_len;
} uip_ext_hdr_opt_padn; } uip_ext_hdr_opt_padn;
#if UIP_CONF_IPV6_RPL
/* RPL option */
typedef struct uip_ext_hdr_opt_rpl {
u8_t opt_type;
u8_t opt_len;
u8_t flags;
u8_t instance;
u16_t senderrank;
} uip_ext_hdr_opt_rpl;
#endif /* UIP_CONF_IPV6_RPL */
/* TCP header */ /* TCP header */
struct uip_tcp_hdr { struct uip_tcp_hdr {
u16_t srcport; u16_t srcport;
@ -1840,6 +1851,10 @@ struct uip_udp_hdr {
/** \brief Destination and Hop By Hop extension headers option types */ /** \brief Destination and Hop By Hop extension headers option types */
#define UIP_EXT_HDR_OPT_PAD1 0 #define UIP_EXT_HDR_OPT_PAD1 0
#define UIP_EXT_HDR_OPT_PADN 1 #define UIP_EXT_HDR_OPT_PADN 1
#if UIP_CONF_IPV6_RPL
#define UIP_EXT_HDR_OPT_RPL 0x63
#endif /* UIP_CONF_IPV6_RPL */
/** @} */ /** @} */
/** @{ */ /** @{ */
@ -1897,8 +1912,13 @@ struct uip_udp_hdr {
*/ */
#define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len) #define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len)
#define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) #define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
#define uip_l2_l3_udp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_UDPH_LEN)
#define uip_l2_l3_tcp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_TCPH_LEN)
#define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len) #define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len)
#define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) #define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
#define uip_l3_udp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_UDPH_LEN)
#define uip_l3_tcp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_TCPH_LEN)
#endif /*UIP_CONF_IPV6*/ #endif /*UIP_CONF_IPV6*/

View file

@ -95,7 +95,7 @@
#endif #endif
#if UIP_CONF_IPV6_RPL #if UIP_CONF_IPV6_RPL
void uip_rpl_input(void); #include "rpl/rpl.h"
#endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6_RPL */
#if UIP_LOGGING == 1 #if UIP_LOGGING == 1
@ -163,6 +163,9 @@ u8_t uip_ext_opt_offset = 0;
#define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_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_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_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
#if UIP_CONF_IPV6_RPL
#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
#endif /* UIP_CONF_IPV6_RPL */
#define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
/** @} */ /** @} */
/** \name Buffer variables /** \name Buffer variables
@ -503,6 +506,24 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
} }
#endif /* UIP_TCP && UIP_ACTIVE_OPEN */ #endif /* UIP_TCP && UIP_ACTIVE_OPEN */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
remove_ext_hdr(void)
{
/* Remove ext header before TCP/UDP processing. */
if(uip_ext_len > 0) {
PRINTF("Cutting ext-header before TCP send (%d)\n", uip_ext_len);
memmove(((uint8_t *)UIP_TCP_BUF) - uip_ext_len, (uint8_t *)UIP_TCP_BUF,
uip_len - UIP_IPH_LEN - uip_ext_len);
uip_len -= uip_ext_len;
/* Update the IP length. */
UIP_IP_BUF->len[0] = (uip_len - UIP_IPH_LEN) >> 8;
UIP_IP_BUF->len[1] = (uip_len - UIP_IPH_LEN) & 0xff;
uip_ext_len = 0;
}
}
/*---------------------------------------------------------------------------*/
#if UIP_UDP #if UIP_UDP
struct uip_udp_conn * struct uip_udp_conn *
uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport) uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport)
@ -828,6 +849,16 @@ ext_hdr_options_process(void)
PRINTF("Processing PADN option\n"); PRINTF("Processing PADN option\n");
uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2; uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2;
break; break;
#if UIP_CONF_IPV6_RPL
case UIP_EXT_HDR_OPT_RPL:
PRINTF("Processing RPL option\n");
if(rpl_verify_header(uip_ext_opt_offset)) {
PRINTF("RPL Option Error : Dropping Packet");
return 1;
}
uip_ext_opt_offset += (UIP_EXT_HDR_OPT_RPL_BUF->opt_len) + 2;
return 0;
#endif /* UIP_CONF_IPV6_RPL */
default: default:
/* /*
* check the two highest order bits of the option * check the two highest order bits of the option
@ -1015,7 +1046,7 @@ uip_process(u8_t flag)
if(flag == UIP_UDP_TIMER) { if(flag == UIP_UDP_TIMER) {
if(uip_udp_conn->lport != 0) { if(uip_udp_conn->lport != 0) {
uip_conn = NULL; uip_conn = NULL;
uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; uip_sappdata = uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len];
uip_len = uip_slen = 0; uip_len = uip_slen = 0;
uip_flags = UIP_POLL; uip_flags = UIP_POLL;
UIP_UDP_APPCALL(); UIP_UDP_APPCALL();
@ -1079,6 +1110,35 @@ uip_process(u8_t flag)
} }
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
/*
* Next header field processing. In IPv6, we can have extension headers,
* if present, the Hop-by-Hop Option must be processed before forwarding
* the packet.
*/
uip_next_hdr = &UIP_IP_BUF->proto;
uip_ext_len = 0;
uip_ext_bitmap = 0;
if(*uip_next_hdr == UIP_PROTO_HBHO) {
#if UIP_CONF_IPV6_CHECKS
uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO;
#endif /*UIP_CONF_IPV6_CHECKS*/
switch(ext_hdr_options_process()) {
case 0:
/*continue*/
uip_next_hdr = &UIP_EXT_BUF->next;
uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
break;
case 1:
/*silently discard*/
goto drop;
case 2:
/* send icmp error message (created in ext_hdr_options_process)
* and discard*/
goto send;
}
}
/* TBD Some Parameter problem messages */ /* TBD Some Parameter problem messages */
if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { !uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
@ -1102,6 +1162,11 @@ uip_process(u8_t flag)
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
goto send; goto send;
} }
#if UIP_CONF_IPV6_RPL
rpl_update_header_empty();
#endif /* UIP_CONF_IPV6_RPL */
UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1; UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
PRINTF("Forwarding packet to "); PRINTF("Forwarding packet to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
@ -1132,7 +1197,6 @@ uip_process(u8_t flag)
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
goto drop; goto drop;
} }
#endif /* UIP_CONF_ROUTER */
/* /*
* Next header field processing. In IPv6, we can have extension headers, * Next header field processing. In IPv6, we can have extension headers,
@ -1141,6 +1205,8 @@ uip_process(u8_t flag)
uip_next_hdr = &UIP_IP_BUF->proto; uip_next_hdr = &UIP_IP_BUF->proto;
uip_ext_len = 0; uip_ext_len = 0;
uip_ext_bitmap = 0; uip_ext_bitmap = 0;
#endif /* UIP_CONF_ROUTER */
while(1) { while(1) {
switch(*uip_next_hdr){ switch(*uip_next_hdr){
#if UIP_TCP #if UIP_TCP
@ -1374,8 +1440,8 @@ uip_process(u8_t flag)
work. If the application sets uip_slen, it has a packet to work. If the application sets uip_slen, it has a packet to
send. */ send. */
#if UIP_UDP_CHECKSUMS #if UIP_UDP_CHECKSUMS
uip_len = uip_len - UIP_IPUDPH_LEN; uip_len = uip_len - uip_l3_udp_hdr_len;
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len];
if(UIP_UDP_BUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { if(UIP_UDP_BUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
UIP_STAT(++uip_stat.udp.drop); UIP_STAT(++uip_stat.udp.drop);
UIP_STAT(++uip_stat.udp.chkerr); UIP_STAT(++uip_stat.udp.chkerr);
@ -1384,7 +1450,7 @@ uip_process(u8_t flag)
goto drop; goto drop;
} }
#else /* UIP_UDP_CHECKSUMS */ #else /* UIP_UDP_CHECKSUMS */
uip_len = uip_len - UIP_IPUDPH_LEN; uip_len = uip_len - uip_l3_udp_hdr_len;
#endif /* UIP_UDP_CHECKSUMS */ #endif /* UIP_UDP_CHECKSUMS */
/* Make sure that the UDP destination port number is not zero. */ /* Make sure that the UDP destination port number is not zero. */
@ -1428,7 +1494,7 @@ uip_process(u8_t flag)
uip_conn = NULL; uip_conn = NULL;
uip_flags = UIP_NEWDATA; uip_flags = UIP_NEWDATA;
uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; uip_sappdata = uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len];
uip_slen = 0; uip_slen = 0;
UIP_UDP_APPCALL(); UIP_UDP_APPCALL();
@ -1438,7 +1504,8 @@ uip_process(u8_t flag)
if(uip_slen == 0) { if(uip_slen == 0) {
goto drop; goto drop;
} }
uip_len = uip_slen + UIP_IPUDPH_LEN; /* TODO: ext_header len here ? */
uip_len = uip_slen + uip_l3_udp_hdr_len; /* UIP_IPUDPH_LEN; */
/* For IPv6, the IP length field does not include the IPv6 IP header /* For IPv6, the IP length field does not include the IPv6 IP header
length. */ length. */
@ -1474,6 +1541,8 @@ uip_process(u8_t flag)
/* TCP input processing. */ /* TCP input processing. */
tcp_input: tcp_input:
remove_ext_hdr();
UIP_STAT(++uip_stat.tcp.recv); UIP_STAT(++uip_stat.tcp.recv);
PRINTF("Receiving TCP packet\n"); PRINTF("Receiving TCP packet\n");
/* Start of TCP input header processing code. */ /* Start of TCP input header processing code. */
@ -1482,13 +1551,14 @@ uip_process(u8_t flag)
checksum. */ checksum. */
UIP_STAT(++uip_stat.tcp.drop); UIP_STAT(++uip_stat.tcp.drop);
UIP_STAT(++uip_stat.tcp.chkerr); UIP_STAT(++uip_stat.tcp.chkerr);
UIP_LOG("tcp: bad checksum."); PRINTF("tcp: bad checksum 0x%04x 0x%04x\n", UIP_TCP_BUF->tcpchksum,
uip_tcpchksum());
goto drop; goto drop;
} }
/* Make sure that the TCP port number is not zero. */ /* Make sure that the TCP port number is not zero. */
if(UIP_TCP_BUF->destport == 0 || UIP_TCP_BUF->srcport == 0) { if(UIP_TCP_BUF->destport == 0 || UIP_TCP_BUF->srcport == 0) {
UIP_LOG("tcp: zero port."); PRINTF("tcp: zero port.");
goto drop; goto drop;
} }
@ -1636,7 +1706,7 @@ uip_process(u8_t flag)
/* Parse the TCP MSS option, if present. */ /* Parse the TCP MSS option, if present. */
if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) {
opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; opt = uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + c];
if(opt == TCP_OPT_END) { if(opt == TCP_OPT_END) {
/* End of options. */ /* End of options. */
break; break;
@ -1644,10 +1714,10 @@ uip_process(u8_t flag)
++c; ++c;
/* NOP option. */ /* NOP option. */
} else if(opt == TCP_OPT_MSS && } else if(opt == TCP_OPT_MSS &&
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
/* An MSS option with the right option length. */ /* An MSS option with the right option length. */
tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 2 + c] << 8) |
(u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; (u16_t)uip_buf[UIP_IPTCPH_LEN + uip_ext_len + UIP_LLH_LEN + 3 + c];
uip_connr->initialmss = uip_connr->mss = uip_connr->initialmss = uip_connr->mss =
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
@ -1656,12 +1726,12 @@ uip_process(u8_t flag)
} else { } else {
/* All other options have a length field, so that we easily /* All other options have a length field, so that we easily
can skip past them. */ can skip past them. */
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { if(uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c] == 0) {
/* If the length field is zero, the options are malformed /* If the length field is zero, the options are malformed
and we don't process them further. */ and we don't process them further. */
break; break;
} }
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; c += uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c];
} }
} }
} }
@ -1684,7 +1754,7 @@ uip_process(u8_t flag)
UIP_TCP_BUF->optdata[1] = TCP_OPT_MSS_LEN; UIP_TCP_BUF->optdata[1] = TCP_OPT_MSS_LEN;
UIP_TCP_BUF->optdata[2] = (UIP_TCP_MSS) / 256; UIP_TCP_BUF->optdata[2] = (UIP_TCP_MSS) / 256;
UIP_TCP_BUF->optdata[3] = (UIP_TCP_MSS) & 255; UIP_TCP_BUF->optdata[3] = (UIP_TCP_MSS) & 255;
uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN + uip_ext_len;
UIP_TCP_BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; UIP_TCP_BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
goto tcp_send; goto tcp_send;
@ -1710,7 +1780,7 @@ uip_process(u8_t flag)
/* uip_len will contain the length of the actual TCP data. This is /* uip_len will contain the length of the actual TCP data. This is
calculated by subtracing the length of the TCP header (in calculated by subtracing the length of the TCP header (in
c) and the length of the IP header (20 bytes). */ c) and the length of the IP header (20 bytes). */
uip_len = uip_len - c - UIP_IPH_LEN; uip_len = uip_len - c - UIP_IPH_LEN - uip_ext_len;
/* First, check if the sequence number of the incoming packet is /* First, check if the sequence number of the incoming packet is
what we're expecting next. If not, we send out an ACK with the what we're expecting next. If not, we send out an ACK with the
@ -1817,7 +1887,7 @@ uip_process(u8_t flag)
/* Parse the TCP MSS option, if present. */ /* Parse the TCP MSS option, if present. */
if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) {
opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c + uip_ext_len];
if(opt == TCP_OPT_END) { if(opt == TCP_OPT_END) {
/* End of options. */ /* End of options. */
break; break;
@ -1825,10 +1895,10 @@ uip_process(u8_t flag)
++c; ++c;
/* NOP option. */ /* NOP option. */
} else if(opt == TCP_OPT_MSS && } else if(opt == TCP_OPT_MSS &&
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len] == TCP_OPT_MSS_LEN) {
/* An MSS option with the right option length. */ /* An MSS option with the right option length. */
tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c + uip_ext_len] << 8) |
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c + uip_ext_len];
uip_connr->initialmss = uip_connr->initialmss =
uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
@ -1837,12 +1907,12 @@ uip_process(u8_t flag)
} else { } else {
/* All other options have a length field, so that we easily /* All other options have a length field, so that we easily
can skip past them. */ can skip past them. */
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len] == 0) {
/* If the length field is zero, the options are malformed /* If the length field is zero, the options are malformed
and we don't process them further. */ and we don't process them further. */
break; break;
} }
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len];
} }
} }
} }
@ -2113,7 +2183,7 @@ uip_process(u8_t flag)
UIP_TCP_BUF->flags = TCP_ACK; UIP_TCP_BUF->flags = TCP_ACK;
tcp_send_nodata: tcp_send_nodata:
uip_len = UIP_IPTCPH_LEN; uip_len = UIP_IPTCPH_LEN; /* TODO: maybe ext_len??? */
tcp_send_noopts: tcp_send_noopts:
UIP_TCP_BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; UIP_TCP_BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;

View file

@ -194,12 +194,12 @@
#define UIP_CONF_IPV6_QUEUE_PKT 0 #define UIP_CONF_IPV6_QUEUE_PKT 0
#endif #endif
#ifndef UIP_CONF_IPV6_CHECKS #ifndef UIP_CONF_IPV6_CHECKS
/** Do we do IPv6 consistency checks (highly recommended, default: yes) */ /** Do we do IPv6 consistency checks (highly recommended, default: yes) */
#define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_CHECKS 1
#endif #endif
#ifndef UIP_CONF_IPV6_REASSEMBLY #ifndef UIP_CONF_IPV6_REASSEMBLY
/** Do we do IPv6 fragmentation (default: no) */ /** Do we do IPv6 fragmentation (default: no) */
#define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_IPV6_REASSEMBLY 0
#endif #endif
@ -209,19 +209,19 @@
#define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_NETIF_MAX_ADDRESSES 3
#endif #endif
#ifndef UIP_CONF_ND6_MAX_PREFIXES #ifndef UIP_CONF_DS6_PREFIX_NBU
/** Default number of IPv6 prefixes associated to the node's interface */ /** Default number of IPv6 prefixes associated to the node's interface */
#define UIP_CONF_ND6_MAX_PREFIXES 3 #define UIP_CONF_DS6_PREFIX_NBU 2
#endif #endif
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS #ifndef UIP_CONF_DS6_NBR_NBU
/** Default number of neighbors that can be stored in the %neighbor cache */ /** Default number of neighbors that can be stored in the %neighbor cache */
#define UIP_CONF_ND6_MAX_NEIGHBORS 4 #define UIP_CONF_DS6_NBR_NBU 4
#endif #endif
#ifndef UIP_CONF_ND6_MAX_DEFROUTERS #ifndef UIP_CONF_DS6_DEFRT_NBU
/** Minimum number of default routers */ /** Minimum number of default routers */
#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_DS6_DEFRT_NBU 2
#endif #endif
/** @} */ /** @} */

View file

@ -240,7 +240,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");
@ -258,7 +258,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);
} }
} }

View file

@ -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) {

View file

@ -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);
} }
} }

View file

@ -4,6 +4,7 @@ CONTIKI=../../..
WITH_UIP6=1 WITH_UIP6=1
UIP_CONF_IPV6=1 UIP_CONF_IPV6=1
CFLAGS+= -DUIP_CONF_IPV6_RPL CFLAGS+= -DUIP_CONF_IPV6_RPL
ifdef WITH_COMPOWER ifdef WITH_COMPOWER

View file

@ -135,8 +135,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");
@ -169,7 +168,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);
} }
} }

View file

@ -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;

View file

@ -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));
} }

View file

@ -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");
} }
@ -133,4 +133,4 @@ void set_net_address(void)
#endif /* FIXED_GLOBAL_ADDRESS */ #endif /* FIXED_GLOBAL_ADDRESS */
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */