Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki
This commit is contained in:
commit
26bc3734eb
29 changed files with 1982 additions and 967 deletions
|
@ -54,9 +54,24 @@
|
|||
#define PRINTADDR(addr)
|
||||
#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 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;
|
||||
|
||||
/** \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;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -145,7 +160,7 @@ create(void)
|
|||
|
||||
/* Set the source PAN ID to the global variable. */
|
||||
params.src_pid = mac_src_pan_id;
|
||||
|
||||
|
||||
/*
|
||||
* Set up the source address using only the long address mode for
|
||||
* phase 1.
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
#include "net/neighbor-info.h"
|
||||
#include "net/neighbor-attr.h"
|
||||
#include "net/uip-ds6.h"
|
||||
#include "net/uip-nd6.h"
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/uip-debug.h"
|
||||
|
@ -104,6 +106,9 @@ neighbor_info_packet_sent(int status, int numtx)
|
|||
{
|
||||
const rimeaddr_t *dest;
|
||||
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);
|
||||
if(rimeaddr_cmp(dest, &rimeaddr_null)) {
|
||||
|
@ -119,6 +124,17 @@ neighbor_info_packet_sent(int status, int numtx)
|
|||
switch(status) {
|
||||
case MAC_TX_OK:
|
||||
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;
|
||||
case MAC_TX_NOACK:
|
||||
packet_metric = ETX_NOACK_PENALTY;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
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
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
293
core/net/rpl/rpl-ext-header.c
Executable 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
215
core/net/rpl/rpl-icmp6.c
Normal file → Executable file
|
@ -81,8 +81,17 @@ void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *);
|
|||
void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *);
|
||||
#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
|
||||
get_global_addr(uip_ipaddr_t *addr)
|
||||
|
@ -135,21 +144,27 @@ set16(uint8_t *buffer, int pos, uint16_t value)
|
|||
static void
|
||||
dis_input(void)
|
||||
{
|
||||
rpl_dag_t *dag;
|
||||
rpl_instance_t *instance;
|
||||
rpl_instance_t *end;
|
||||
|
||||
/* DAG Information Solicitation */
|
||||
PRINTF("RPL: Received a DIS from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
||||
if(dag != NULL) {
|
||||
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
PRINTF("RPL: Multicast DIS => reset DIO timer\n");
|
||||
rpl_reset_dio_timer(dag, 0);
|
||||
} else {
|
||||
PRINTF("RPL: Unicast DIS, reply to sender\n");
|
||||
dio_output(dag, &UIP_IP_BUF->srcipaddr);
|
||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||
if(instance->used == 1 ) {
|
||||
#if RPL_LEAF_ONLY
|
||||
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
#else /* !RPL_LEAF_ONLY */
|
||||
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
PRINTF("RPL: Multicast DIS => reset DIO timer\n");
|
||||
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;
|
||||
|
||||
#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
|
||||
|
||||
/* Process the DIO base option. */
|
||||
|
@ -236,6 +251,7 @@ dio_input(void)
|
|||
dio.rank = get16(buffer, i);
|
||||
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);
|
||||
|
||||
dio.grounded = buffer[i] & RPL_DIO_GROUNDED;
|
||||
|
@ -249,6 +265,10 @@ dio_input(void)
|
|||
memcpy(&dio.dag_id, buffer + 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. */
|
||||
for(; i < buffer_length; i += len) {
|
||||
subopt_type = buffer[i];
|
||||
|
@ -274,7 +294,6 @@ dio_input(void)
|
|||
RPL_STAT(rpl_stats.malformed_msgs++);
|
||||
return;
|
||||
}
|
||||
|
||||
dio.mc.type = buffer[i + 2];
|
||||
dio.mc.flags = buffer[i + 3] << 1;
|
||||
dio.mc.flags |= buffer[i + 4] >> 7;
|
||||
|
@ -375,19 +394,35 @@ dio_input(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;
|
||||
int pos;
|
||||
#if !RPL_LEAF_ONLY
|
||||
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 */
|
||||
pos = 0;
|
||||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
buffer[pos++] = dag->instance_id;
|
||||
buffer[pos++] = instance->instance_id;
|
||||
buffer[pos++] = dag->version;
|
||||
|
||||
#if RPL_LEAF_ONLY
|
||||
set16(buffer, pos, INFINITE_RANK);
|
||||
#else /* RPL_LEAF_ONLY */
|
||||
set16(buffer, pos, dag->rank);
|
||||
#endif /* RPL_LEAF_ONLY */
|
||||
pos += 2;
|
||||
|
||||
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++] = dag->mop << RPL_DIO_MOP_SHIFT;
|
||||
buffer[pos++] = ++dag->dtsn_out;
|
||||
buffer[pos] |= instance->mop << RPL_DIO_MOP_SHIFT;
|
||||
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 */
|
||||
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));
|
||||
pos += 16;
|
||||
|
||||
if(dag->mc.type != RPL_DAG_MC_NONE) {
|
||||
dag->of->update_metric_container(dag);
|
||||
#if !RPL_LEAF_ONLY
|
||||
if(instance->mc.type != RPL_DAG_MC_NONE) {
|
||||
instance->of->update_metric_container(instance);
|
||||
|
||||
buffer[pos++] = RPL_OPTION_DAG_METRIC_CONTAINER;
|
||||
buffer[pos++] = 6;
|
||||
buffer[pos++] = dag->mc.type;
|
||||
buffer[pos++] = dag->mc.flags >> 1;
|
||||
buffer[pos] = (dag->mc.flags & 1) << 7;
|
||||
buffer[pos++] |= (dag->mc.aggr << 4) | dag->mc.prec;
|
||||
|
||||
if(dag->mc.type == RPL_DAG_MC_ETX) {
|
||||
buffer[pos++] = instance->mc.type;
|
||||
buffer[pos++] = instance->mc.flags >> 1;
|
||||
buffer[pos] = (instance->mc.flags & 1) << 7;
|
||||
buffer[pos++] |= (instance->mc.aggr << 4) | instance->mc.prec;
|
||||
if(instance->mc.type == RPL_DAG_MC_ETX) {
|
||||
buffer[pos++] = 2;
|
||||
set16(buffer, pos, dag->mc.obj.etx);
|
||||
set16(buffer, pos, instance->mc.obj.etx);
|
||||
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++] = dag->mc.obj.energy.flags;
|
||||
buffer[pos++] = dag->mc.obj.energy.energy_est;
|
||||
buffer[pos++] = instance->mc.obj.energy.flags;
|
||||
buffer[pos++] = instance->mc.obj.energy.energy_est;
|
||||
} else {
|
||||
PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
|
||||
(unsigned)dag->mc.type);
|
||||
(unsigned)instance->mc.type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* !RPL_LEAF_ONLY */
|
||||
|
||||
/* Always add a DAG configuration option. */
|
||||
buffer[pos++] = RPL_OPTION_DAG_CONF;
|
||||
buffer[pos++] = 14;
|
||||
buffer[pos++] = 0; /* No Auth, PCS = 0 */
|
||||
buffer[pos++] = dag->dio_intdoubl;
|
||||
buffer[pos++] = dag->dio_intmin;
|
||||
buffer[pos++] = dag->dio_redundancy;
|
||||
set16(buffer, pos, dag->max_rankinc);
|
||||
buffer[pos++] = instance->dio_intdoubl;
|
||||
buffer[pos++] = instance->dio_intmin;
|
||||
buffer[pos++] = instance->dio_redundancy;
|
||||
set16(buffer, pos, instance->max_rankinc);
|
||||
pos += 2;
|
||||
set16(buffer, pos, dag->min_hoprankinc);
|
||||
set16(buffer, pos, instance->min_hoprankinc);
|
||||
pos += 2;
|
||||
/* OCP is in the DAG_CONF option */
|
||||
set16(buffer, pos, dag->of->ocp);
|
||||
set16(buffer, pos, instance->of->ocp);
|
||||
pos += 2;
|
||||
buffer[pos++] = 0; /* reserved */
|
||||
buffer[pos++] = dag->default_lifetime;
|
||||
set16(buffer, pos, dag->lifetime_unit);
|
||||
buffer[pos++] = instance->default_lifetime;
|
||||
set16(buffer, pos, instance->lifetime_unit);
|
||||
pos += 2;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#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! */
|
||||
if(uc_addr == NULL) {
|
||||
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_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
||||
} else {
|
||||
PRINTF("RPL: Sending unicast-DIO with rank %u to ",
|
||||
(unsigned)dag->rank);
|
||||
(unsigned)instance->current_dag->rank);
|
||||
PRINT6ADDR(uc_addr);
|
||||
PRINTF("\n");
|
||||
uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos);
|
||||
}
|
||||
#endif /* RPL_LEAF_ONLY */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -491,10 +542,11 @@ dao_input(void)
|
|||
{
|
||||
uip_ipaddr_t dao_sender_addr;
|
||||
rpl_dag_t *dag;
|
||||
rpl_instance_t *instance;
|
||||
unsigned char *buffer;
|
||||
uint16_t sequence;
|
||||
uint8_t instance_id;
|
||||
rpl_lifetime_t lifetime;
|
||||
uint8_t lifetime;
|
||||
uint8_t prefixlen;
|
||||
uint8_t flags;
|
||||
uint8_t subopt_type;
|
||||
|
@ -520,32 +572,37 @@ dao_input(void)
|
|||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
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
|
||||
|
||||
pos = 0;
|
||||
instance_id = buffer[pos++];
|
||||
|
||||
dag = rpl_get_dag(instance_id);
|
||||
if(dag == NULL) {
|
||||
PRINTF("RPL: Ignoring a DAO for a different RPL instance (%u)\n",
|
||||
instance = rpl_get_instance(instance_id);
|
||||
if(instance == NULL) {
|
||||
PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n",
|
||||
instance_id);
|
||||
return;
|
||||
}
|
||||
|
||||
lifetime = dag->default_lifetime;
|
||||
lifetime = instance->default_lifetime;
|
||||
|
||||
flags = buffer[pos++];
|
||||
/* reserved */
|
||||
pos++;
|
||||
sequence = buffer[pos++];
|
||||
|
||||
dag = instance->current_dag;
|
||||
/* Is the DAGID present? */
|
||||
if(flags & RPL_DAO_D_FLAG) {
|
||||
/* Currently the DAG ID is ignored since we only use global
|
||||
RPL Instance IDs. */
|
||||
if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) {
|
||||
PRINTF("RPL: Ignoring a DAO for a DODAG different from ours\n");
|
||||
return;
|
||||
}
|
||||
pos += 16;
|
||||
} else {
|
||||
/* Perhaps, there are verification to do but ... */
|
||||
}
|
||||
|
||||
/* Check if there are any RPL options present. */
|
||||
|
@ -561,7 +618,7 @@ dao_input(void)
|
|||
|
||||
switch(subopt_type) {
|
||||
case RPL_OPTION_TARGET:
|
||||
/* handle the target option */
|
||||
/* Handle the target option. */
|
||||
prefixlen = buffer[i + 3];
|
||||
memset(&prefix, 0, sizeof(prefix));
|
||||
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: ",
|
||||
(unsigned)lifetime, (unsigned)prefixlen);
|
||||
(unsigned)lifetime, (unsigned)prefixlen);
|
||||
PRINT6ADDR(&prefix);
|
||||
PRINTF("\n");
|
||||
|
||||
|
@ -585,7 +642,7 @@ dao_input(void)
|
|||
|
||||
if(lifetime == ZERO_LIFETIME) {
|
||||
/* 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 ");
|
||||
PRINT6ADDR(&prefix);
|
||||
PRINTF("\n");
|
||||
|
@ -601,25 +658,25 @@ dao_input(void)
|
|||
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
||||
/* Check whether this is a DAO forwarding loop. */
|
||||
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",
|
||||
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->updated = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
|
||||
if(rep == NULL) {
|
||||
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
|
||||
if(rep == NULL) {
|
||||
RPL_STAT(rpl_stats.mem_overflows++);
|
||||
PRINTF("RPL: Could not add a route after receiving a DAO\n");
|
||||
return;
|
||||
}
|
||||
RPL_STAT(rpl_stats.mem_overflows++);
|
||||
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;
|
||||
|
||||
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
|
||||
|
@ -629,16 +686,18 @@ dao_input(void)
|
|||
PRINTF("\n");
|
||||
uip_icmp6_send(&dag->preferred_parent->addr,
|
||||
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
|
||||
dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
||||
dao_output(rpl_parent_t *n, uint8_t lifetime)
|
||||
{
|
||||
rpl_dag_t *dag;
|
||||
rpl_instance_t *instance;
|
||||
unsigned char *buffer;
|
||||
uint8_t prefixlen;
|
||||
uip_ipaddr_t addr;
|
||||
|
@ -652,7 +711,7 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
|||
}
|
||||
|
||||
if(n == NULL) {
|
||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
||||
dag = rpl_get_any_dag();
|
||||
if(dag == NULL) {
|
||||
PRINTF("RPL: Did not join a DAG before sending DAO\n");
|
||||
return;
|
||||
|
@ -661,23 +720,32 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
|
|||
dag = n->dag;
|
||||
}
|
||||
|
||||
instance = dag->instance;
|
||||
|
||||
#ifdef RPL_DEBUG_DAO_OUTPUT
|
||||
RPL_DEBUG_DAO_OUTPUT(n);
|
||||
#endif
|
||||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
|
||||
++dao_sequence;
|
||||
RPL_LOLLIPOP_INCREMENT(dao_sequence);
|
||||
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
|
||||
buffer[pos++] = RPL_DAO_K_FLAG; /* DAO ACK request, no DODAGID */
|
||||
#else
|
||||
buffer[pos++] = 0; /* No DAO ACK request, no DODAGID */
|
||||
#endif
|
||||
buffer[pos] |= RPL_DAO_K_FLAG;
|
||||
#endif /* RPL_CONF_DAO_ACK */
|
||||
++pos;
|
||||
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 */
|
||||
prefixlen = sizeof(prefix) * CHAR_BIT;
|
||||
|
@ -726,9 +794,6 @@ dao_ack_input(void)
|
|||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
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];
|
||||
sequence = buffer[2];
|
||||
|
@ -741,7 +806,7 @@ dao_ack_input(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;
|
||||
|
||||
|
@ -751,7 +816,7 @@ dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence)
|
|||
|
||||
buffer = UIP_ICMP_PAYLOAD;
|
||||
|
||||
buffer[0] = dag->instance_id;
|
||||
buffer[0] = instance->instance_id;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = sequence;
|
||||
buffer[3] = 0;
|
||||
|
|
|
@ -52,13 +52,15 @@
|
|||
static void reset(rpl_dag_t *);
|
||||
static void parent_state_callback(rpl_parent_t *, int, int);
|
||||
static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
|
||||
static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_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 = {
|
||||
reset,
|
||||
parent_state_callback,
|
||||
best_parent,
|
||||
best_dag,
|
||||
calculate_rank,
|
||||
update_metric_container,
|
||||
1
|
||||
|
@ -86,14 +88,14 @@ typedef uint16_t rpl_path_metric_t;
|
|||
static rpl_path_metric_t
|
||||
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 p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric);
|
||||
}
|
||||
|
||||
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;
|
||||
} 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) {
|
||||
base_rank = p->rank;
|
||||
}
|
||||
|
@ -132,6 +134,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_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 *
|
||||
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. */
|
||||
|
||||
min_diff = RPL_DAG_MC_ETX_DIVISOR /
|
||||
min_diff = RPL_DAG_MC_ETX_DIVISOR /
|
||||
PARENT_SWITCH_THRESHOLD_DIV;
|
||||
|
||||
p1_metric = calculate_path_metric(p1);
|
||||
|
@ -164,18 +192,26 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
|||
}
|
||||
|
||||
static void
|
||||
update_metric_container(rpl_dag_t *dag)
|
||||
update_metric_container(rpl_instance_t *instance)
|
||||
{
|
||||
rpl_path_metric_t path_metric;
|
||||
rpl_dag_t *dag;
|
||||
#if RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
||||
uint8_t type;
|
||||
#endif
|
||||
|
||||
dag->mc.flags = RPL_DAG_MC_FLAG_P;
|
||||
dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
||||
dag->mc.prec = 0;
|
||||
instance->mc.flags = RPL_DAG_MC_FLAG_P;
|
||||
instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
|
||||
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;
|
||||
} else {
|
||||
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
|
||||
|
||||
dag->mc.type = RPL_DAG_MC_ETX;
|
||||
dag->mc.length = sizeof(dag->mc.obj.etx);
|
||||
dag->mc.obj.etx = path_metric;
|
||||
instance->mc.type = RPL_DAG_MC_ETX;
|
||||
instance->mc.length = sizeof(instance->mc.obj.etx);
|
||||
instance->mc.obj.etx = path_metric;
|
||||
|
||||
PRINTF("RPL: My path ETX to the root is %u.%u\n",
|
||||
dag->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,
|
||||
(instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);
|
||||
|
||||
#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
||||
|
||||
dag->mc.type = RPL_DAG_MC_ENERGY;
|
||||
dag->mc.length = sizeof(dag->mc.obj.energy);
|
||||
instance->mc.type = RPL_DAG_MC_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;
|
||||
} else {
|
||||
type = RPL_DAG_MC_ENERGY_TYPE_BATTERY;
|
||||
}
|
||||
|
||||
dag->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
|
||||
dag->mc.obj.energy.energy_est = path_metric;
|
||||
instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE;
|
||||
instance->mc.obj.energy.energy_est = path_metric;
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
static void reset(rpl_dag_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 void update_metric_container(rpl_dag_t *);
|
||||
|
||||
|
@ -55,6 +56,7 @@ rpl_of_t rpl_of0 = {
|
|||
reset,
|
||||
NULL,
|
||||
best_parent,
|
||||
best_dag,
|
||||
calculate_rank,
|
||||
update_metric_container,
|
||||
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 *
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,16 @@
|
|||
#define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */
|
||||
#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. */
|
||||
|
||||
/* The default value for the DAO timer. */
|
||||
|
@ -108,8 +118,8 @@
|
|||
/* Default route lifetime as a multiple of the lifetime unit. */
|
||||
#define RPL_DEFAULT_LIFETIME 0xff
|
||||
|
||||
#define RPL_LIFETIME(dag, lifetime) \
|
||||
((unsigned long)(dag)->lifetime_unit * lifetime)
|
||||
#define RPL_LIFETIME(instance, lifetime) \
|
||||
(((unsigned long)(instance)->lifetime_unit) * lifetime)
|
||||
|
||||
#ifndef RPL_CONF_MIN_HOPRANKINC
|
||||
#define DEFAULT_MIN_HOPRANKINC 256
|
||||
|
@ -118,13 +128,13 @@
|
|||
#endif
|
||||
#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. */
|
||||
#define BASE_RANK 0
|
||||
|
||||
/* Rank of a root node. */
|
||||
#define ROOT_RANK(dag) (dag)->min_hoprankinc
|
||||
#define ROOT_RANK(instance) (instance)->min_hoprankinc
|
||||
|
||||
#define INFINITE_RANK 0xffff
|
||||
|
||||
|
@ -208,7 +218,7 @@ struct rpl_dio {
|
|||
uint8_t dag_intdoubl;
|
||||
uint8_t dag_intmin;
|
||||
uint8_t dag_redund;
|
||||
rpl_lifetime_t default_lifetime;
|
||||
uint8_t default_lifetime;
|
||||
uint16_t lifetime_unit;
|
||||
rpl_rank_t dag_max_rankinc;
|
||||
rpl_rank_t dag_min_hoprankinc;
|
||||
|
@ -241,33 +251,44 @@ extern rpl_stats_t rpl_stats;
|
|||
#define RPL_STAT(code)
|
||||
#endif /* RPL_CONF_STATS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Instances */
|
||||
extern rpl_instance_t instance_table[];
|
||||
rpl_instance_t *default_instance;
|
||||
|
||||
/* ICMPv6 functions for RPL. */
|
||||
void dis_output(uip_ipaddr_t *addr);
|
||||
void dio_output(rpl_dag_t *, uip_ipaddr_t *uc_addr);
|
||||
void dao_output(rpl_parent_t *, rpl_lifetime_t lifetime);
|
||||
void dao_ack_output(rpl_dag_t *, uip_ipaddr_t *, uint8_t);
|
||||
void uip_rpl_input(void);
|
||||
void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr);
|
||||
void dao_output(rpl_parent_t *, uint8_t lifetime);
|
||||
void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t);
|
||||
|
||||
/* RPL logic functions. */
|
||||
void rpl_join_dag(rpl_dag_t *);
|
||||
void rpl_local_repair(rpl_dag_t *dag);
|
||||
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from);
|
||||
void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio);
|
||||
void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio);
|
||||
void rpl_local_repair(rpl_instance_t *instance);
|
||||
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. */
|
||||
rpl_dag_t *rpl_alloc_dag(uint8_t);
|
||||
void rpl_free_dag(rpl_dag_t *);
|
||||
rpl_dag_t *rpl_alloc_dodag(uint8_t, uip_ipaddr_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. */
|
||||
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 *);
|
||||
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_dag_t *rpl_select_dodag(rpl_instance_t *instance,rpl_parent_t *parent);
|
||||
void rpl_recalculate_ranks(void);
|
||||
|
||||
/* RPL routing table functions. */
|
||||
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,
|
||||
int prefix_len, uip_ipaddr_t *next_hop);
|
||||
void rpl_purge_routes(void);
|
||||
|
@ -276,8 +297,8 @@ void rpl_purge_routes(void);
|
|||
rpl_of_t *rpl_find_of(rpl_ocp_t);
|
||||
|
||||
/* Timer functions. */
|
||||
void rpl_schedule_dao(rpl_dag_t *);
|
||||
void rpl_reset_dio_timer(rpl_dag_t *, uint8_t);
|
||||
void rpl_schedule_dao(rpl_instance_t *);
|
||||
void rpl_reset_dio_timer(rpl_instance_t *, uint8_t);
|
||||
void rpl_reset_periodic_timer(void);
|
||||
|
||||
/* Route poisoning. */
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
static struct ctimer periodic_timer;
|
||||
|
||||
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 uint16_t next_dis;
|
||||
|
@ -69,7 +69,7 @@ handle_periodic_timer(void *ptr)
|
|||
/* handle DIS */
|
||||
#ifdef RPL_DIS_SEND
|
||||
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;
|
||||
dis_output(NULL);
|
||||
}
|
||||
|
@ -78,17 +78,17 @@ handle_periodic_timer(void *ptr)
|
|||
}
|
||||
/************************************************************************/
|
||||
static void
|
||||
new_dio_interval(rpl_dag_t *dag)
|
||||
new_dio_interval(rpl_instance_t *instance)
|
||||
{
|
||||
uint32_t time;
|
||||
|
||||
/* TODO: too small timer intervals for many cases */
|
||||
time = 1UL << dag->dio_intcurrent;
|
||||
time = 1UL << instance->dio_intcurrent;
|
||||
|
||||
/* Convert from milliseconds to CLOCK_TICKS. */
|
||||
time = (time * CLOCK_SECOND) / 1000;
|
||||
|
||||
dag->dio_next_delay = time;
|
||||
instance->dio_next_delay = time;
|
||||
|
||||
/* random number between I/2 and I */
|
||||
time = time >> 1;
|
||||
|
@ -99,36 +99,36 @@ new_dio_interval(rpl_dag_t *dag)
|
|||
* operate efficiently. Therefore we need to calculate the delay between
|
||||
* the randomized time and the start time of the next interval.
|
||||
*/
|
||||
dag->dio_next_delay -= time;
|
||||
dag->dio_send = 1;
|
||||
instance->dio_next_delay -= time;
|
||||
instance->dio_send = 1;
|
||||
|
||||
#if RPL_CONF_STATS
|
||||
/* keep some stats */
|
||||
dag->dio_totint++;
|
||||
dag->dio_totrecv += dag->dio_counter;
|
||||
instance->dio_totint++;
|
||||
instance->dio_totrecv += instance->dio_counter;
|
||||
ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n",
|
||||
DAG_RANK(dag->rank, dag),
|
||||
(10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc,
|
||||
dag->version,
|
||||
dag->dio_totint, dag->dio_totsend,
|
||||
dag->dio_totrecv,dag->dio_intcurrent,
|
||||
dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE");
|
||||
DAG_RANK(instance->current_dag->rank, instance),
|
||||
(10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc,
|
||||
instance->current_dag->version,
|
||||
instance->dio_totint, instance->dio_totsend,
|
||||
instance->dio_totrecv,instance->dio_intcurrent,
|
||||
instance->current_dag->rank == ROOT_RANK(instance) ? "BLUE" : "ORANGE");
|
||||
#endif /* RPL_CONF_STATS */
|
||||
|
||||
/* reset the redundancy counter */
|
||||
dag->dio_counter = 0;
|
||||
instance->dio_counter = 0;
|
||||
|
||||
/* schedule the timer */
|
||||
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
|
||||
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");
|
||||
if(!dio_send_ok) {
|
||||
|
@ -136,33 +136,33 @@ handle_dio_timer(void *ptr)
|
|||
dio_send_ok = 1;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(dag->dio_send) {
|
||||
if(instance->dio_send) {
|
||||
/* 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
|
||||
dag->dio_totsend++;
|
||||
instance->dio_totsend++;
|
||||
#endif /* RPL_CONF_STATS */
|
||||
dio_output(dag, NULL);
|
||||
dio_output(instance, NULL);
|
||||
} else {
|
||||
PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n",
|
||||
dag->dio_counter, dag->dio_redundancy);
|
||||
instance->dio_counter, instance->dio_redundancy);
|
||||
}
|
||||
dag->dio_send = 0;
|
||||
PRINTF("RPL: Scheduling DIO timer %u ticks in future (sent)\n",
|
||||
dag->dio_next_delay);
|
||||
ctimer_set(&dag->dio_timer, dag->dio_next_delay, handle_dio_timer, dag);
|
||||
instance->dio_send = 0;
|
||||
PRINTF("RPL: Scheduling DIO timer %"PRIu32" ticks in future (sent)\n",
|
||||
instance->dio_next_delay);
|
||||
ctimer_set(&instance->dio_timer, instance->dio_next_delay, handle_dio_timer, instance);
|
||||
} else {
|
||||
/* check if we need to double interval */
|
||||
if(dag->dio_intcurrent < dag->dio_intmin + dag->dio_intdoubl) {
|
||||
dag->dio_intcurrent++;
|
||||
PRINTF("RPL: DIO Timer interval doubled %d\n", dag->dio_intcurrent);
|
||||
if(instance->dio_intcurrent < instance->dio_intmin + instance->dio_intdoubl) {
|
||||
instance->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);
|
||||
}
|
||||
/************************************************************************/
|
||||
/* Resets the DIO timer in the DAG to its minimal interval. */
|
||||
/* Resets the DIO timer in the instance to its minimal interval. */
|
||||
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(force || dag->dio_intcurrent > dag->dio_intmin) {
|
||||
dag->dio_counter = 0;
|
||||
dag->dio_intcurrent = dag->dio_intmin;
|
||||
new_dio_interval(dag);
|
||||
#if !RPL_LEAF_ONLY
|
||||
/* Do not reset if we are already on the minimum interval,
|
||||
unless forced to do so. */
|
||||
if(force || instance->dio_intcurrent > instance->dio_intmin) {
|
||||
instance->dio_counter = 0;
|
||||
instance->dio_intcurrent = instance->dio_intmin;
|
||||
new_dio_interval(instance);
|
||||
}
|
||||
#if RPL_CONF_STATS
|
||||
rpl_stats.resets++;
|
||||
#endif
|
||||
#endif /* RPL_CONF_STATS */
|
||||
#endif /* RPL_LEAF_ONLY */
|
||||
}
|
||||
/************************************************************************/
|
||||
static void
|
||||
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) {
|
||||
PRINTF("RPL: Postpone DAO transmission... \n");
|
||||
ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag);
|
||||
if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
|
||||
PRINTF("RPL: Postpone DAO transmission\n");
|
||||
ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
/* 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 {
|
||||
PRINTF("RPL: No suitable DAO parent\n");
|
||||
}
|
||||
ctimer_stop(&dag->dao_timer);
|
||||
ctimer_stop(&instance->dao_timer);
|
||||
}
|
||||
/************************************************************************/
|
||||
void
|
||||
rpl_schedule_dao(rpl_dag_t *dag)
|
||||
rpl_schedule_dao(rpl_instance_t *instance)
|
||||
{
|
||||
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");
|
||||
} else {
|
||||
expiration_time = DEFAULT_DAO_LATENCY / 2 +
|
||||
(random_rand() % (DEFAULT_DAO_LATENCY));
|
||||
PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n",
|
||||
(unsigned)expiration_time);
|
||||
ctimer_set(&dag->dao_timer, expiration_time,
|
||||
handle_dao_timer, dag);
|
||||
ctimer_set(&instance->dao_timer, expiration_time,
|
||||
handle_dao_timer, instance);
|
||||
}
|
||||
}
|
||||
/************************************************************************/
|
||||
|
|
|
@ -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 *
|
||||
rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
||||
PRINTF("RPL: Added a route to ");
|
||||
|
@ -123,8 +140,9 @@ static void
|
|||
rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
|
||||
{
|
||||
uip_ipaddr_t ipaddr;
|
||||
rpl_dag_t *dag;
|
||||
rpl_parent_t *parent;
|
||||
rpl_instance_t *instance;
|
||||
rpl_instance_t *end;
|
||||
|
||||
uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
||||
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);
|
||||
PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
|
||||
|
||||
dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
|
||||
if(dag == NULL) {
|
||||
return;
|
||||
}
|
||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||
if(instance->used == 1 ) {
|
||||
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(parent == NULL) {
|
||||
if(!known) {
|
||||
PRINTF("RPL: Deleting routes installed by DAOs received from ");
|
||||
PRINT6ADDR(&ipaddr);
|
||||
PRINTF("\n");
|
||||
uip_ds6_route_rm_by_nexthop(&ipaddr);
|
||||
if(instance->of->parent_state_callback != NULL) {
|
||||
instance->of->parent_state_callback(parent, known, etx);
|
||||
}
|
||||
if(!known) {
|
||||
PRINTF("RPL: Removing parent ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx);
|
||||
parent->rank = INFINITE_RANK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Trigger DAG rank recalculation. */
|
||||
parent->updated = 1;
|
||||
|
||||
parent->link_metric = etx;
|
||||
|
||||
if(dag->of->parent_state_callback != NULL) {
|
||||
dag->of->parent_state_callback(parent, known, etx);
|
||||
}
|
||||
|
||||
if(!known) {
|
||||
PRINTF("RPL: Removing parent ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINTF(" because of bad connectivity (ETX %d)\n", etx);
|
||||
parent->rank = INFINITE_RANK;
|
||||
PRINTF("RPL: Deleting routes installed by DAOs received from ");
|
||||
PRINT6ADDR(&ipaddr);
|
||||
PRINTF("\n");
|
||||
uip_ds6_route_rm_by_nexthop(&ipaddr);
|
||||
}
|
||||
}
|
||||
/************************************************************************/
|
||||
void
|
||||
rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
||||
{
|
||||
rpl_dag_t *dag;
|
||||
rpl_parent_t *p;
|
||||
|
||||
/* This only handles one DODAG - if multiple we need to check all */
|
||||
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;
|
||||
}
|
||||
rpl_instance_t *instance;
|
||||
rpl_instance_t *end;
|
||||
|
||||
if(!nbr->isused) {
|
||||
PRINTF("RPL: Removing neighbor ");
|
||||
PRINT6ADDR(&nbr->ipaddr);
|
||||
PRINTF("\n");
|
||||
p = rpl_find_parent(dag, &nbr->ipaddr);
|
||||
if(p != NULL) {
|
||||
p->rank = INFINITE_RANK;
|
||||
/* Trigger DAG rank recalculation. */
|
||||
p->updated = 1;
|
||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||
if(instance->used == 1 ) {
|
||||
p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
|
||||
if(p != NULL) {
|
||||
p->rank = INFINITE_RANK;
|
||||
/* Trigger DAG rank recalculation. */
|
||||
p->updated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +208,7 @@ rpl_init(void)
|
|||
{
|
||||
uip_ipaddr_t rplmaddr;
|
||||
PRINTF("RPL started\n");
|
||||
default_instance = NULL;
|
||||
|
||||
rpl_reset_periodic_timer();
|
||||
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
||||
|
|
|
@ -73,19 +73,77 @@
|
|||
#endif /* RPL_CONF_OF */
|
||||
|
||||
/* 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. */
|
||||
#define RPL_PARENT_COUNT(dag) list_length((dag)->parents)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef uint16_t rpl_rank_t;
|
||||
typedef uint8_t rpl_lifetime_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. */
|
||||
#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;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct rpl_instance;
|
||||
struct rpl_dag;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct rpl_parent {
|
||||
|
@ -153,6 +212,35 @@ struct rpl_parent {
|
|||
};
|
||||
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)
|
||||
*
|
||||
|
@ -171,6 +259,10 @@ typedef struct rpl_parent rpl_parent_t;
|
|||
*
|
||||
* 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)
|
||||
*
|
||||
* 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 (*parent_state_callback)(rpl_parent_t *, int, int);
|
||||
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);
|
||||
void (*update_metric_container)(struct rpl_dag *);
|
||||
void (*update_metric_container)( rpl_instance_t *);
|
||||
rpl_ocp_t ocp;
|
||||
};
|
||||
typedef struct rpl_of rpl_of_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 {
|
||||
/* Instance */
|
||||
struct rpl_instance {
|
||||
/* DAG configuration */
|
||||
rpl_metric_container_t mc;
|
||||
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" */
|
||||
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 version;
|
||||
uint8_t grounded;
|
||||
uint8_t used;
|
||||
uint8_t dtsn_out;
|
||||
uint8_t mop;
|
||||
uint8_t preference;
|
||||
uint8_t dio_intdoubl;
|
||||
uint8_t dio_intmin;
|
||||
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 min_hoprankinc;
|
||||
uint8_t used;
|
||||
uint8_t default_lifetime;
|
||||
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
|
||||
uint16_t dio_totint;
|
||||
uint16_t dio_totsend;
|
||||
|
@ -241,19 +318,23 @@ struct rpl_dag {
|
|||
uint32_t dio_next_delay; /* delay for completion of dio interval */
|
||||
struct ctimer dio_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. */
|
||||
void rpl_init(void);
|
||||
rpl_dag_t *rpl_set_root(uip_ipaddr_t *);
|
||||
int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len);
|
||||
int rpl_repair_dag(rpl_dag_t *dag);
|
||||
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from);
|
||||
rpl_dag_t *rpl_get_dag(int instance_id);
|
||||
void uip_rpl_input(void);
|
||||
rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id);
|
||||
int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len);
|
||||
int rpl_repair_root(uint8_t 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 */
|
||||
|
|
118
core/net/tcpip.c
118
core/net/tcpip.c
|
@ -27,10 +27,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*
|
||||
* $Id: tcpip.c,v 1.30 2010/10/29 05:36:07 adamdunkels Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* 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 Julien Abeille <jabeille@cisco.com> (IPv6 related code)
|
||||
*/
|
||||
|
||||
#include "contiki-net.h"
|
||||
|
||||
#include "net/uip-split.h"
|
||||
|
||||
#include "net/uip-packetqueue.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
#include "net/uip-nd6.h"
|
||||
#include "net/uip-ds6.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#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)
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/uip-debug.h"
|
||||
|
||||
#if UIP_LOGGING
|
||||
#include <stdio.h>
|
||||
|
@ -78,21 +67,21 @@ void uip_log(char *msg);
|
|||
#ifdef UIP_FALLBACK_INTERFACE
|
||||
extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
|
||||
#endif
|
||||
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
void rpl_init(void);
|
||||
#include "rpl/rpl.h"
|
||||
#endif
|
||||
|
||||
process_event_t tcpip_event;
|
||||
#if UIP_CONF_ICMP6
|
||||
process_event_t tcpip_icmp6_event;
|
||||
#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;
|
||||
|
||||
#if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
|
||||
/*timer for reassembly*/
|
||||
/* Timer for reassembly. */
|
||||
extern struct etimer uip_reass_timer;
|
||||
#endif
|
||||
|
||||
|
@ -412,21 +401,19 @@ eventhandler(process_event_t ev, process_data_t data)
|
|||
cptr->appstate.p = PROCESS_NONE;
|
||||
cptr->tcpstateflags = UIP_CLOSED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* UIP_TCP */
|
||||
#if UIP_UDP
|
||||
{
|
||||
register struct uip_udp_conn *cptr;
|
||||
|
||||
for(cptr = &uip_udp_conns[0];
|
||||
cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
|
||||
if(cptr->appstate.p == p) {
|
||||
cptr->lport = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* UIP_UDP */
|
||||
break;
|
||||
|
@ -477,12 +464,12 @@ eventhandler(process_event_t ev, process_data_t data)
|
|||
* check the different timers for neighbor discovery and
|
||||
* stateless autoconfiguration
|
||||
*/
|
||||
/*if(data == &uip_nd6_timer_periodic &&
|
||||
etimer_expired(&uip_nd6_timer_periodic)) {
|
||||
uip_nd6_periodic();
|
||||
/*if(data == &uip_ds6_timer_periodic &&
|
||||
etimer_expired(&uip_ds6_timer_periodic)) {
|
||||
uip_ds6_periodic();
|
||||
tcpip_ipv6_output();
|
||||
}*/
|
||||
#if !UIP_CONF_ROUTER
|
||||
#if !UIP_CONF_ROUTER
|
||||
if(data == &uip_ds6_timer_rs &&
|
||||
etimer_expired(&uip_ds6_timer_rs)){
|
||||
uip_ds6_send_rs();
|
||||
|
@ -551,22 +538,24 @@ void
|
|||
tcpip_ipv6_output(void)
|
||||
{
|
||||
uip_ds6_nbr_t *nbr = NULL;
|
||||
uip_ipaddr_t* nexthop;
|
||||
|
||||
uip_ipaddr_t *nexthop;
|
||||
|
||||
if(uip_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(uip_len > UIP_LINK_MTU) {
|
||||
UIP_LOG("tcpip_ipv6_output: Packet to big");
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
|
||||
UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
/* Next hop determination */
|
||||
nbr = NULL;
|
||||
|
@ -578,10 +567,18 @@ tcpip_ipv6_output(void)
|
|||
if(locrt == NULL) {
|
||||
if((nexthop = uip_ds6_defrt_choose()) == NULL) {
|
||||
#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();
|
||||
#else
|
||||
PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
|
||||
#endif
|
||||
#endif /* !UIP_FALLBACK_INTERFACE */
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -589,16 +586,20 @@ tcpip_ipv6_output(void)
|
|||
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) {
|
||||
// printf("add1 %d\n", nexthop->u8[15]);
|
||||
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
|
||||
// printf("add n\n");
|
||||
uip_len = 0;
|
||||
return;
|
||||
} else {
|
||||
#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) {
|
||||
memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, 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);
|
||||
}
|
||||
|
||||
stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000);
|
||||
stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
|
||||
nbr->nscount = 1;
|
||||
}
|
||||
} else {
|
||||
if(nbr->state == NBR_INCOMPLETE) {
|
||||
PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
/* copy outgoing pkt in the queuing buffer for later transmmit and set
|
||||
the destination nbr to nbr */
|
||||
/* Copy outgoing pkt in the queuing buffer for later transmit and set
|
||||
the destination nbr to nbr. */
|
||||
if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
|
||||
memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, 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*/
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
/* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep
|
||||
sending in parallel see rfc 4861 Node behavior in section 7.7.3*/
|
||||
|
||||
/* Send in parallel if we are running NUD (nbc state is either STALE,
|
||||
DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */
|
||||
if(nbr->state == NBR_STALE) {
|
||||
nbr->state = NBR_DELAY;
|
||||
stimer_set(&(nbr->reachable),
|
||||
UIP_ND6_DELAY_FIRST_PROBE_TIME);
|
||||
stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
|
||||
nbr->nscount = 0;
|
||||
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
|
||||
/* 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
|
||||
* 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) {
|
||||
uip_len = uip_packetqueue_buflen(&nbr->packethandle);
|
||||
memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
|
||||
uip_packetqueue_free(&nbr->packethandle);
|
||||
tcpip_output(&(nbr->lladdr));
|
||||
tcpip_output(&nbr->lladdr);
|
||||
}
|
||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
|
||||
|
||||
|
@ -676,14 +665,13 @@ tcpip_ipv6_output(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*multicast IP destination address */
|
||||
|
||||
/* Multicast IP destination address. */
|
||||
tcpip_output(NULL);
|
||||
uip_len = 0;
|
||||
uip_ext_len = 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_UDP
|
||||
void
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
/**
|
||||
* \file
|
||||
* IPv6 data structures handling functions
|
||||
* IPv6 data structures handling functions.
|
||||
* 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 Julien Abeille <jabeille@cisco.com>
|
||||
*/
|
||||
|
@ -148,16 +148,19 @@ uip_ds6_init(void)
|
|||
void
|
||||
uip_ds6_periodic(void)
|
||||
{
|
||||
|
||||
/* Periodic processing on unicast addresses */
|
||||
for(locaddr = uip_ds6_if.addr_list;
|
||||
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
|
||||
if(locaddr->isused) {
|
||||
if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
|
||||
uip_ds6_addr_rm(locaddr);
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
} else if((locaddr->state == ADDR_TENTATIVE)
|
||||
&& (locaddr->dadnscount <= uip_ds6_if.maxdadns)
|
||||
&& (timer_expired(&locaddr->dadtimer))) {
|
||||
uip_ds6_dad(locaddr);
|
||||
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -366,6 +369,24 @@ uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr)
|
|||
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_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) {
|
||||
locaddr->isused = 1;
|
||||
uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
|
||||
locaddr->state = ADDR_TENTATIVE;
|
||||
locaddr->type = type;
|
||||
if(vlifetime == 0) {
|
||||
locaddr->isinfinite = 1;
|
||||
|
@ -557,10 +577,15 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
|
|||
locaddr->isinfinite = 0;
|
||||
stimer_set(&(locaddr->vlifetime), vlifetime);
|
||||
}
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
locaddr->state = ADDR_TENTATIVE;
|
||||
timer_set(&locaddr->dadtimer,
|
||||
random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
|
||||
CLOCK_SECOND));
|
||||
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_ds6_maddr_add(&loc_fipaddr);
|
||||
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);
|
||||
locroute->metric = metric;
|
||||
|
||||
#ifdef UIP_DS6_ROUTE_STATE_TYPE
|
||||
memset(&locroute->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
|
||||
#endif
|
||||
|
||||
PRINTF("DS6: adding route: ");
|
||||
PRINT6ADDR(ipaddr);
|
||||
PRINTF(" via ");
|
||||
|
@ -884,6 +913,7 @@ get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
|
|||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
void
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_CONF_ROUTER
|
||||
#if UIP_ND6_SEND_RA
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_ds6_send_ra_sollicited(void)
|
||||
{
|
||||
|
|
|
@ -124,6 +124,13 @@
|
|||
#endif
|
||||
#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 */
|
||||
|
@ -209,8 +216,10 @@ typedef struct uip_ds6_addr {
|
|||
uint8_t type;
|
||||
uint8_t isinfinite;
|
||||
struct stimer vlifetime;
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
struct timer dadtimer;
|
||||
uint8_t dadnscount;
|
||||
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
} uip_ds6_addr_t;
|
||||
|
||||
/** \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);
|
||||
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_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 */
|
||||
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 */
|
||||
void uip_ds6_dad(uip_ds6_addr_t * ifaddr);
|
||||
|
||||
/** \brief Callback when DAD failed */
|
||||
int uip_ds6_dad_failed(uip_ds6_addr_t * ifaddr);
|
||||
#endif /* UIP_ND6_DEF_MAXDADNS */
|
||||
|
||||
/** \brief Source address selection, see RFC 3484 */
|
||||
void uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst);
|
||||
|
|
|
@ -60,14 +60,25 @@
|
|||
#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_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 */
|
||||
static uip_ipaddr_t tmp_ipaddr;
|
||||
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
#include "rpl/rpl.h"
|
||||
#endif /* UIP_CONF_IPV6_RPL */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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
|
||||
* headers in the request otherwise we need to remove the extension
|
||||
|
@ -78,7 +89,7 @@ uip_icmp6_echo_request_input(void)
|
|||
PRINTF("to");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
|
||||
/* IP header */
|
||||
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 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));
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
if ((temp_ext_len=rpl_invert_header())) {
|
||||
/* If there were other extension headers*/
|
||||
UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6;
|
||||
if (uip_ext_len != temp_ext_len) {
|
||||
uip_len -= (uip_ext_len - temp_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 remaining 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 - 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
|
||||
* checksum
|
||||
*/
|
||||
uip_ext_len = 0;
|
||||
|
||||
/* Note: now UIP_ICMP_BUF points to the beginning of the echo reply */
|
||||
UIP_ICMP_BUF->type = ICMP6_ECHO_REPLY;
|
||||
UIP_ICMP_BUF->icode = 0;
|
||||
UIP_ICMP_BUF->icmpchksum = 0;
|
||||
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
|
||||
|
||||
|
||||
PRINTF("Sending Echo Reply to");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
|
@ -127,29 +162,45 @@ uip_icmp6_echo_request_input(void)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
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*/
|
||||
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
|
||||
uip_len = 0;
|
||||
return;
|
||||
if (uip_ext_len) {
|
||||
if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
|
||||
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 */
|
||||
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;
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
uip_ext_len = rpl_invert_header();
|
||||
#else /* UIP_CONF_IPV6_RPL */
|
||||
uip_ext_len = 0;
|
||||
#endif /* UIP_CONF_IPV6_RPL */
|
||||
|
||||
memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + UIP_ICMP6_ERROR_LEN,
|
||||
(void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - UIP_ICMP6_ERROR_LEN);
|
||||
/* remember data of original packet before shifting */
|
||||
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->tcflow = 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;
|
||||
|
||||
/* 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;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
UIP_ICMP_BUF->type = type;
|
||||
UIP_ICMP_BUF->icode = code;
|
||||
UIP_ICMP6_ERROR_BUF->param = uip_htonl(param);
|
||||
|
|
|
@ -76,16 +76,7 @@
|
|||
|
||||
/*------------------------------------------------------------------*/
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#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
|
||||
#include "net/uip-debug.h"
|
||||
|
||||
#if UIP_LOGGING
|
||||
#include <stdio.h>
|
||||
|
@ -154,11 +145,11 @@ create_llao(uint8_t *llao, uint8_t type) {
|
|||
void
|
||||
uip_nd6_ns_input(void)
|
||||
{
|
||||
PRINTF("Received NS from");
|
||||
PRINTF("Received NS from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("to");
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("with target address");
|
||||
PRINTF(" with target address");
|
||||
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
|
||||
PRINTF("\n");
|
||||
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);
|
||||
if(addr != NULL) {
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
|
||||
/* DAD CASE */
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
|
@ -242,6 +234,11 @@ uip_nd6_ns_input(void)
|
|||
uip_ds6_dad_failed(addr);
|
||||
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_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_STAT(++uip_stat.nd6.sent);
|
||||
PRINTF("Sending NA to");
|
||||
PRINTF("Sending NA to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("with target address");
|
||||
PRINTF(" with target address ");
|
||||
PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
|
||||
PRINTF("\n");
|
||||
return;
|
||||
|
@ -441,9 +438,11 @@ uip_nd6_na_input(void)
|
|||
addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
|
||||
/* Message processing, including TLLAO if any */
|
||||
if(addr != NULL) {
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
if(addr->state == ADDR_TENTATIVE) {
|
||||
uip_ds6_dad_failed(addr);
|
||||
}
|
||||
#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
PRINTF("NA received is bad\n");
|
||||
goto discard;
|
||||
} else {
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
#include "net/uip.h"
|
||||
#include "sys/stimer.h"
|
||||
/**
|
||||
* \name General
|
||||
* @{
|
||||
* \name General
|
||||
* @{
|
||||
*/
|
||||
/** \brief HOP LIMIT to be used when sending ND messages (255) */
|
||||
#define UIP_ND6_HOP_LIMIT 255
|
||||
|
@ -57,29 +57,21 @@
|
|||
#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
|
||||
|
||||
/** \name Configuration options */
|
||||
/** @{ */
|
||||
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS
|
||||
/** \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*/
|
||||
/** @} */
|
||||
|
||||
#endif /* UIP_CONF_LL_802154 */
|
||||
#else /* UIP_CONF_ND6_DEF_MAXDADNS */
|
||||
#define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS
|
||||
#endif /* UIP_CONF_ND6_DEF_MAXDADNS */
|
||||
|
||||
/** \name RFC 4861 Host constant */
|
||||
/** @{ */
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
|
||||
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
|
||||
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
|
||||
/** @} */
|
||||
|
||||
|
@ -115,7 +107,7 @@
|
|||
#ifdef UIP_CONF_ND6_RETRANS_TIMER
|
||||
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
|
||||
#else
|
||||
#define UIP_ND6_RETRANS_TIMER 1000
|
||||
#define UIP_ND6_RETRANS_TIMER 1000
|
||||
#endif
|
||||
#define UIP_ND6_DELAY_FIRST_PROBE_TIME 5
|
||||
#define UIP_ND6_MIN_RANDOM_FACTOR(x) (x / 2)
|
||||
|
@ -140,8 +132,8 @@
|
|||
|
||||
/** \name ND6 message length (excluding options) */
|
||||
/** @{ */
|
||||
#define UIP_ND6_NA_LEN 20
|
||||
#define UIP_ND6_NS_LEN 20
|
||||
#define UIP_ND6_NA_LEN 20
|
||||
#define UIP_ND6_NS_LEN 20
|
||||
#define UIP_ND6_RA_LEN 12
|
||||
#define UIP_ND6_RS_LEN 4
|
||||
/** @} */
|
||||
|
@ -160,7 +152,7 @@
|
|||
#define UIP_ND6_OPT_SHORT_LLAO_LEN 8
|
||||
#define UIP_ND6_OPT_LONG_LLAO_LEN 16
|
||||
/** \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*/
|
||||
#if UIP_CONF_LL_80211
|
||||
/* If the interface is 802.11 */
|
||||
|
@ -179,93 +171,18 @@
|
|||
#define UIP_ND6_NA_FLAG_ROUTER 0x80
|
||||
#define UIP_ND6_NA_FLAG_SOLICITED 0x40
|
||||
#define UIP_ND6_NA_FLAG_OVERRIDE 0x20
|
||||
#define UIP_ND6_RA_FLAG_ONLINK 0x80
|
||||
#define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40
|
||||
#define UIP_ND6_RA_FLAG_ONLINK 0x80
|
||||
#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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* \brief A neighbor solicitation constant part
|
||||
*
|
||||
*
|
||||
* Possible option is: SLLAO
|
||||
*/
|
||||
typedef struct uip_nd6_ns {
|
||||
|
@ -275,19 +192,19 @@ typedef struct uip_nd6_ns {
|
|||
|
||||
/**
|
||||
* \brief A neighbor advertisement constant part.
|
||||
*
|
||||
*
|
||||
* Possible option is: TLLAO
|
||||
*/
|
||||
*/
|
||||
typedef struct uip_nd6_na {
|
||||
uint8_t flagsreserved;
|
||||
uint8_t reserved[3];
|
||||
uip_ipaddr_t tgtipaddr;
|
||||
} uip_nd6_na;
|
||||
|
||||
/**
|
||||
/**
|
||||
* \brief A router solicitation constant part
|
||||
*
|
||||
* Possible option is: SLLAO
|
||||
*
|
||||
* Possible option is: SLLAO
|
||||
*/
|
||||
typedef struct uip_nd6_rs {
|
||||
uint32_t reserved;
|
||||
|
@ -295,7 +212,7 @@ typedef struct uip_nd6_rs {
|
|||
|
||||
/**
|
||||
* \brief A router advertisement constant part
|
||||
*
|
||||
*
|
||||
* Possible options are: SLLAO, MTU, Prefix Information
|
||||
*/
|
||||
typedef struct uip_nd6_ra {
|
||||
|
@ -308,13 +225,13 @@ typedef struct uip_nd6_ra {
|
|||
|
||||
/**
|
||||
* \brief A redirect message constant part
|
||||
*
|
||||
*
|
||||
* Possible options are: TLLAO, redirected header
|
||||
*/
|
||||
typedef struct uip_nd6_redirect {
|
||||
uint32_t reserved;
|
||||
uip_ipaddr_t tgtipaddress;
|
||||
uip_ipaddr_t destipaddress;
|
||||
uip_ipaddr_t tgtipaddress;
|
||||
uip_ipaddr_t destipaddress;
|
||||
} uip_nd6_redirect;
|
||||
/** @} */
|
||||
|
||||
|
@ -357,102 +274,6 @@ typedef struct 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
|
||||
* @{
|
||||
|
@ -467,7 +288,7 @@ void
|
|||
* address)
|
||||
*
|
||||
* 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:
|
||||
* -- I already sent a NS, hence I win
|
||||
* -- 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
|
||||
* function: set src, dst, tgt address in the three cases, then for all cases
|
||||
* set the rest, including SLLAO
|
||||
*
|
||||
*
|
||||
*/
|
||||
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 dest pointer to ip address to send the NS, for DAD or ADDR Resol,
|
||||
* 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
|
||||
* interface should be used."
|
||||
* 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
|
||||
* a SLLAO option, otherwise no.
|
||||
*/
|
||||
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
|
||||
|
@ -528,7 +349,7 @@ uip_nd6_na_input(void);
|
|||
#if UIP_ND6_SEND_RA
|
||||
/**
|
||||
* \brief Process a Router Solicitation
|
||||
*
|
||||
*
|
||||
*/
|
||||
void uip_nd6_rs_input(void);
|
||||
|
||||
|
@ -543,12 +364,12 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest);
|
|||
|
||||
/**
|
||||
* \brief Send a Router Solicitation
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* SHOULD be included otherwise
|
||||
*/
|
||||
|
@ -559,7 +380,7 @@ void uip_nd6_rs_output(void);
|
|||
* \brief process a Router Advertisement
|
||||
*
|
||||
* - 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 SLLAO option: update entry in neighbor cache
|
||||
* - If prefix option: start autoconf, add prefix to prefix list
|
||||
|
@ -570,13 +391,13 @@ uip_nd6_ra_input(void);
|
|||
|
||||
|
||||
void
|
||||
uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
||||
uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
||||
/*--------------------------------------*/
|
||||
/******* ANNEX - message formats ********/
|
||||
/*--------------------------------------*/
|
||||
|
||||
/*
|
||||
* RS format. possible option is SLLAO
|
||||
/*
|
||||
* RS format. possible option is SLLAO
|
||||
* 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
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
@ -644,7 +465,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
|||
* | Options ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Redirect message format. Possible options are TLLAO and Redirected header
|
||||
*
|
||||
* 0 1 2 3
|
||||
|
@ -673,7 +494,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
|||
* | Options ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-
|
||||
*
|
||||
*
|
||||
*
|
||||
* SLLAO/TLLAO option:
|
||||
* 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
|
||||
|
@ -681,7 +502,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
|||
* | Type | Length | Link-Layer Address ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*
|
||||
*
|
||||
* Prefix information option
|
||||
* 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
|
||||
|
@ -712,8 +533,8 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
|||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | MTU |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Redirected header option
|
||||
*
|
||||
* 0 1 2 3
|
||||
|
@ -728,7 +549,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr);
|
|||
* | |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
*/
|
||||
#endif /* __UIP_ND6_H__ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1770,6 +1770,17 @@ typedef struct uip_ext_hdr_opt_padn {
|
|||
u8_t opt_len;
|
||||
} 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 */
|
||||
struct uip_tcp_hdr {
|
||||
u16_t srcport;
|
||||
|
@ -1840,6 +1851,10 @@ struct uip_udp_hdr {
|
|||
/** \brief Destination and Hop By Hop extension headers option types */
|
||||
#define UIP_EXT_HDR_OPT_PAD1 0
|
||||
#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_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_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*/
|
||||
|
||||
|
||||
|
|
120
core/net/uip6.c
120
core/net/uip6.c
|
@ -95,7 +95,7 @@
|
|||
#endif
|
||||
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
void uip_rpl_input(void);
|
||||
#include "rpl/rpl.h"
|
||||
#endif /* UIP_CONF_IPV6_RPL */
|
||||
|
||||
#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_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])
|
||||
#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])
|
||||
/** @} */
|
||||
/** \name Buffer variables
|
||||
|
@ -503,6 +506,24 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
|
|||
}
|
||||
#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
|
||||
struct uip_udp_conn *
|
||||
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");
|
||||
uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2;
|
||||
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:
|
||||
/*
|
||||
* check the two highest order bits of the option
|
||||
|
@ -1015,7 +1046,7 @@ uip_process(u8_t flag)
|
|||
if(flag == UIP_UDP_TIMER) {
|
||||
if(uip_udp_conn->lport != 0) {
|
||||
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_flags = UIP_POLL;
|
||||
UIP_UDP_APPCALL();
|
||||
|
@ -1079,6 +1110,35 @@ uip_process(u8_t flag)
|
|||
}
|
||||
|
||||
#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 */
|
||||
if(!uip_ds6_is_my_addr(&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);
|
||||
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;
|
||||
PRINTF("Forwarding packet to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
|
@ -1132,7 +1197,6 @@ uip_process(u8_t flag)
|
|||
UIP_STAT(++uip_stat.ip.drop);
|
||||
goto drop;
|
||||
}
|
||||
#endif /* UIP_CONF_ROUTER */
|
||||
|
||||
/*
|
||||
* 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_ext_len = 0;
|
||||
uip_ext_bitmap = 0;
|
||||
#endif /* UIP_CONF_ROUTER */
|
||||
|
||||
while(1) {
|
||||
switch(*uip_next_hdr){
|
||||
#if UIP_TCP
|
||||
|
@ -1374,8 +1440,8 @@ uip_process(u8_t flag)
|
|||
work. If the application sets uip_slen, it has a packet to
|
||||
send. */
|
||||
#if UIP_UDP_CHECKSUMS
|
||||
uip_len = uip_len - UIP_IPUDPH_LEN;
|
||||
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
|
||||
uip_len = uip_len - uip_l3_udp_hdr_len;
|
||||
uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len];
|
||||
if(UIP_UDP_BUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
|
||||
UIP_STAT(++uip_stat.udp.drop);
|
||||
UIP_STAT(++uip_stat.udp.chkerr);
|
||||
|
@ -1384,7 +1450,7 @@ uip_process(u8_t flag)
|
|||
goto drop;
|
||||
}
|
||||
#else /* UIP_UDP_CHECKSUMS */
|
||||
uip_len = uip_len - UIP_IPUDPH_LEN;
|
||||
uip_len = uip_len - uip_l3_udp_hdr_len;
|
||||
#endif /* UIP_UDP_CHECKSUMS */
|
||||
|
||||
/* Make sure that the UDP destination port number is not zero. */
|
||||
|
@ -1428,7 +1494,7 @@ uip_process(u8_t flag)
|
|||
|
||||
uip_conn = NULL;
|
||||
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_UDP_APPCALL();
|
||||
|
||||
|
@ -1438,7 +1504,8 @@ uip_process(u8_t flag)
|
|||
if(uip_slen == 0) {
|
||||
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
|
||||
length. */
|
||||
|
@ -1474,6 +1541,8 @@ uip_process(u8_t flag)
|
|||
/* TCP input processing. */
|
||||
tcp_input:
|
||||
|
||||
remove_ext_hdr();
|
||||
|
||||
UIP_STAT(++uip_stat.tcp.recv);
|
||||
PRINTF("Receiving TCP packet\n");
|
||||
/* Start of TCP input header processing code. */
|
||||
|
@ -1482,13 +1551,14 @@ uip_process(u8_t flag)
|
|||
checksum. */
|
||||
UIP_STAT(++uip_stat.tcp.drop);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Make sure that the TCP port number is not zero. */
|
||||
if(UIP_TCP_BUF->destport == 0 || UIP_TCP_BUF->srcport == 0) {
|
||||
UIP_LOG("tcp: zero port.");
|
||||
PRINTF("tcp: zero port.");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
@ -1636,7 +1706,7 @@ uip_process(u8_t flag)
|
|||
/* Parse the TCP MSS option, if present. */
|
||||
if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
|
||||
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) {
|
||||
/* End of options. */
|
||||
break;
|
||||
|
@ -1644,10 +1714,10 @@ uip_process(u8_t flag)
|
|||
++c;
|
||||
/* NOP option. */
|
||||
} 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. */
|
||||
tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
(u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
|
||||
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_ext_len + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss = uip_connr->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
|
@ -1656,12 +1726,12 @@ uip_process(u8_t flag)
|
|||
} else {
|
||||
/* All other options have a length field, so that we easily
|
||||
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
|
||||
and we don't process them further. */
|
||||
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[2] = (UIP_TCP_MSS) / 256;
|
||||
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;
|
||||
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
|
||||
calculated by subtracing the length of the TCP header (in
|
||||
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
|
||||
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. */
|
||||
if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
|
||||
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) {
|
||||
/* End of options. */
|
||||
break;
|
||||
|
@ -1825,10 +1895,10 @@ uip_process(u8_t flag)
|
|||
++c;
|
||||
/* NOP option. */
|
||||
} 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. */
|
||||
tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
|
||||
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_ext_len];
|
||||
uip_connr->initialmss =
|
||||
uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
|
@ -1837,12 +1907,12 @@ uip_process(u8_t flag)
|
|||
} else {
|
||||
/* All other options have a length field, so that we easily
|
||||
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
|
||||
and we don't process them further. */
|
||||
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;
|
||||
|
||||
tcp_send_nodata:
|
||||
uip_len = UIP_IPTCPH_LEN;
|
||||
uip_len = UIP_IPTCPH_LEN; /* TODO: maybe ext_len??? */
|
||||
|
||||
tcp_send_noopts:
|
||||
UIP_TCP_BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
|
||||
|
|
|
@ -194,12 +194,12 @@
|
|||
#define UIP_CONF_IPV6_QUEUE_PKT 0
|
||||
#endif
|
||||
|
||||
#ifndef UIP_CONF_IPV6_CHECKS
|
||||
#ifndef UIP_CONF_IPV6_CHECKS
|
||||
/** Do we do IPv6 consistency checks (highly recommended, default: yes) */
|
||||
#define UIP_CONF_IPV6_CHECKS 1
|
||||
#endif
|
||||
|
||||
#ifndef UIP_CONF_IPV6_REASSEMBLY
|
||||
#ifndef UIP_CONF_IPV6_REASSEMBLY
|
||||
/** Do we do IPv6 fragmentation (default: no) */
|
||||
#define UIP_CONF_IPV6_REASSEMBLY 0
|
||||
#endif
|
||||
|
@ -209,19 +209,19 @@
|
|||
#define UIP_CONF_NETIF_MAX_ADDRESSES 3
|
||||
#endif
|
||||
|
||||
#ifndef UIP_CONF_ND6_MAX_PREFIXES
|
||||
#ifndef UIP_CONF_DS6_PREFIX_NBU
|
||||
/** 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
|
||||
|
||||
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS
|
||||
#ifndef UIP_CONF_DS6_NBR_NBU
|
||||
/** 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
|
||||
|
||||
#ifndef UIP_CONF_ND6_MAX_DEFROUTERS
|
||||
#ifndef UIP_CONF_DS6_DEFRT_NBU
|
||||
/** Minimum number of default routers */
|
||||
#define UIP_CONF_ND6_MAX_DEFROUTERS 2
|
||||
#define UIP_CONF_DS6_DEFRT_NBU 2
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
|||
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) {
|
||||
rpl_set_prefix(dag, &prefix, 64);
|
||||
PRINTF("created a new RPL dag\n");
|
||||
|
@ -258,7 +258,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
|||
PROCESS_YIELD();
|
||||
if (ev == sensors_event && data == &button_sensor) {
|
||||
PRINTF("Initiating global repair\n");
|
||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
||||
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ collect_common_net_print(void)
|
|||
{
|
||||
rpl_dag_t *dag;
|
||||
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) {
|
||||
PRINTF("Preferred parent: ");
|
||||
PRINT6ADDR(&dag->preferred_parent->addr);
|
||||
|
@ -128,7 +129,8 @@ collect_common_send(void)
|
|||
rimeaddr_copy(&parent, &rimeaddr_null);
|
||||
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) {
|
||||
preferred_parent = dag->preferred_parent;
|
||||
if(preferred_parent != NULL) {
|
||||
|
|
|
@ -151,8 +151,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
|||
root_if = uip_ds6_addr_lookup(&ipaddr);
|
||||
if(root_if != NULL) {
|
||||
rpl_dag_t *dag;
|
||||
rpl_set_root((uip_ip6addr_t *)&ipaddr);
|
||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
||||
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr);
|
||||
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
||||
rpl_set_prefix(dag, &ipaddr, 64);
|
||||
PRINTF("created a new RPL dag\n");
|
||||
|
@ -181,7 +180,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
|||
tcpip_handler();
|
||||
} else if (ev == sensors_event && data == &button_sensor) {
|
||||
PRINTF("Initiaing global repair\n");
|
||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
||||
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ CONTIKI=../../..
|
|||
|
||||
WITH_UIP6=1
|
||||
UIP_CONF_IPV6=1
|
||||
|
||||
CFLAGS+= -DUIP_CONF_IPV6_RPL
|
||||
|
||||
ifdef WITH_COMPOWER
|
||||
|
|
|
@ -135,8 +135,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
|||
root_if = uip_ds6_addr_lookup(&ipaddr);
|
||||
if(root_if != NULL) {
|
||||
rpl_dag_t *dag;
|
||||
rpl_set_root((uip_ip6addr_t *)&ipaddr);
|
||||
dag = rpl_get_dag(RPL_ANY_INSTANCE);
|
||||
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr);
|
||||
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
|
||||
rpl_set_prefix(dag, &ipaddr, 64);
|
||||
PRINTF("created a new RPL dag\n");
|
||||
|
@ -169,7 +168,7 @@ PROCESS_THREAD(udp_server_process, ev, data)
|
|||
tcpip_handler();
|
||||
} else if (ev == sensors_event && data == &button_sensor) {
|
||||
PRINTF("Initiaing global repair\n");
|
||||
rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
||||
rpl_repair_root(RPL_DEFAULT_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -620,11 +620,11 @@ extern uip_ds6_netif_t uip_ds6_if;
|
|||
}
|
||||
|
||||
case 'G':
|
||||
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;
|
||||
|
||||
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"));
|
||||
break;
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ PROCESS_THREAD(border_router_process, ev, data)
|
|||
{ rpl_dag_t *dag;
|
||||
char buf[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 */
|
||||
/* 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) {
|
||||
PROCESS_YIELD();
|
||||
/* Local and global dag repair can be done from the jackdaw menu */
|
||||
// rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64);
|
||||
// rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ void set_net_address(void)
|
|||
print_addresses();
|
||||
|
||||
#if RPL_BORDER_ROUTER
|
||||
dag = rpl_set_root(&ipaddr);
|
||||
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,&ipaddr);
|
||||
if(dag != NULL) {
|
||||
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 /* UIP_CONF_IPV6 */
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
|
Loading…
Add table
Reference in a new issue