mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-09-11 21:55:41 +00:00
This is a fix for Contiki RPL so that it fully supports DAO ACK in an end-to-end fashion. When DAO is sent it will be forwarded upwards as before. DAO ACK will be forwarded downwards until it reach the node that initiated the DAO ACK and unlike before it is not a single-hop DAO ACK but it is fully reaching the RPL ROOT before any DAO ACK is sent back. DAO ACK also now fully support different status messages (success / fail).
336 lines
12 KiB
C
336 lines
12 KiB
C
/*
|
|
* Copyright (c) 2010, 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
|
|
* Private declarations for ContikiRPL.
|
|
* \author
|
|
* Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
|
|
*/
|
|
|
|
#ifndef RPL_PRIVATE_H
|
|
#define RPL_PRIVATE_H
|
|
|
|
#include "net/rpl/rpl.h"
|
|
|
|
#include "lib/list.h"
|
|
#include "net/ip/uip.h"
|
|
#include "sys/clock.h"
|
|
#include "sys/ctimer.h"
|
|
#include "net/ipv6/uip-ds6.h"
|
|
#include "net/ipv6/multicast/uip-mcast6.h"
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/** \brief Is IPv6 address addr the link-local, all-RPL-nodes
|
|
multicast address? */
|
|
#define uip_is_addr_linklocal_rplnodes_mcast(addr) \
|
|
((addr)->u8[0] == 0xff) && \
|
|
((addr)->u8[1] == 0x02) && \
|
|
((addr)->u16[1] == 0) && \
|
|
((addr)->u16[2] == 0) && \
|
|
((addr)->u16[3] == 0) && \
|
|
((addr)->u16[4] == 0) && \
|
|
((addr)->u16[5] == 0) && \
|
|
((addr)->u16[6] == 0) && \
|
|
((addr)->u8[14] == 0) && \
|
|
((addr)->u8[15] == 0x1a))
|
|
|
|
/** \brief Set IP address addr to the link-local, all-rpl-nodes
|
|
multicast address. */
|
|
#define uip_create_linklocal_rplnodes_mcast(addr) \
|
|
uip_ip6addr((addr), 0xff02, 0, 0, 0, 0, 0, 0, 0x001a)
|
|
/*---------------------------------------------------------------------------*/
|
|
/* RPL message types */
|
|
#define RPL_CODE_DIS 0x00 /* DAG Information Solicitation */
|
|
#define RPL_CODE_DIO 0x01 /* DAG Information Option */
|
|
#define RPL_CODE_DAO 0x02 /* Destination Advertisement Option */
|
|
#define RPL_CODE_DAO_ACK 0x03 /* DAO acknowledgment */
|
|
#define RPL_CODE_SEC_DIS 0x80 /* Secure DIS */
|
|
#define RPL_CODE_SEC_DIO 0x81 /* Secure DIO */
|
|
#define RPL_CODE_SEC_DAO 0x82 /* Secure DAO */
|
|
#define RPL_CODE_SEC_DAO_ACK 0x83 /* Secure DAO ACK */
|
|
|
|
/* RPL control message options. */
|
|
#define RPL_OPTION_PAD1 0
|
|
#define RPL_OPTION_PADN 1
|
|
#define RPL_OPTION_DAG_METRIC_CONTAINER 2
|
|
#define RPL_OPTION_ROUTE_INFO 3
|
|
#define RPL_OPTION_DAG_CONF 4
|
|
#define RPL_OPTION_TARGET 5
|
|
#define RPL_OPTION_TRANSIT 6
|
|
#define RPL_OPTION_SOLICITED_INFO 7
|
|
#define RPL_OPTION_PREFIX_INFO 8
|
|
#define RPL_OPTION_TARGET_DESC 9
|
|
|
|
#define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */
|
|
#define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */
|
|
|
|
#define RPL_DAO_ACK_UNCONDITIONAL_ACCEPT 0
|
|
#define RPL_DAO_ACK_ACCEPT 1 /* 1 - 127 is OK but not good */
|
|
#define RPL_DAO_ACK_UNABLE_TO_ACCEPT 128 /* >127 is fail */
|
|
|
|
#define RPL_DAO_ACK_TIMEOUT -1
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* 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. */
|
|
|
|
/* DAO transmissions are always delayed by RPL_DAO_DELAY +/- RPL_DAO_DELAY/2 */
|
|
#ifdef RPL_CONF_DAO_DELAY
|
|
#define RPL_DAO_DELAY RPL_CONF_DAO_DELAY
|
|
#else /* RPL_CONF_DAO_DELAY */
|
|
#define RPL_DAO_DELAY (CLOCK_SECOND * 4)
|
|
#endif /* RPL_CONF_DAO_DELAY */
|
|
|
|
/* Delay between reception of a no-path DAO and actual route removal */
|
|
#ifdef RPL_CONF_NOPATH_REMOVAL_DELAY
|
|
#define RPL_NOPATH_REMOVAL_DELAY RPL_CONF_NOPATH_REMOVAL_DELAY
|
|
#else /* RPL_CONF_NOPATH_REMOVAL_DELAY */
|
|
#define RPL_NOPATH_REMOVAL_DELAY 60
|
|
#endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */
|
|
|
|
#define RPL_DAO_MAX_RETRANSMISSIONS 5
|
|
#define RPL_DAO_RETRANSMISSION_TIMEOUT (5 * CLOCK_SECOND)
|
|
|
|
/* Special value indicating immediate removal. */
|
|
#define RPL_ZERO_LIFETIME 0
|
|
|
|
#define RPL_LIFETIME(instance, lifetime) \
|
|
((unsigned long)(instance)->lifetime_unit * (lifetime))
|
|
|
|
#ifndef RPL_CONF_MIN_HOPRANKINC
|
|
#define RPL_MIN_HOPRANKINC 256
|
|
#else
|
|
#define RPL_MIN_HOPRANKINC RPL_CONF_MIN_HOPRANKINC
|
|
#endif
|
|
#define RPL_MAX_RANKINC (7 * RPL_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(instance) (instance)->min_hoprankinc
|
|
|
|
#define INFINITE_RANK 0xffff
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#define RPL_INSTANCE_LOCAL_FLAG 0x80
|
|
#define RPL_INSTANCE_D_FLAG 0x40
|
|
|
|
/* Values that tell where a route came from. */
|
|
#define RPL_ROUTE_FROM_INTERNAL 0
|
|
#define RPL_ROUTE_FROM_UNICAST_DAO 1
|
|
#define RPL_ROUTE_FROM_MULTICAST_DAO 2
|
|
#define RPL_ROUTE_FROM_DIO 3
|
|
|
|
/* DAG Mode of Operation */
|
|
#define RPL_MOP_NO_DOWNWARD_ROUTES 0
|
|
#define RPL_MOP_NON_STORING 1
|
|
#define RPL_MOP_STORING_NO_MULTICAST 2
|
|
#define RPL_MOP_STORING_MULTICAST 3
|
|
|
|
#ifdef RPL_CONF_MOP
|
|
#define RPL_MOP_DEFAULT RPL_CONF_MOP
|
|
#else /* RPL_CONF_MOP */
|
|
#if RPL_CONF_MULTICAST
|
|
#define RPL_MOP_DEFAULT RPL_MOP_STORING_MULTICAST
|
|
#else
|
|
#define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST
|
|
#endif /* UIP_IPV6_MULTICAST_RPL */
|
|
#endif /* RPL_CONF_MOP */
|
|
|
|
/* Emit a pre-processor error if the user configured multicast with bad MOP */
|
|
#if RPL_CONF_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST)
|
|
#error "RPL Multicast requires RPL_MOP_DEFAULT==3. Check contiki-conf.h"
|
|
#endif
|
|
|
|
/* Multicast Route Lifetime as a multiple of the lifetime unit */
|
|
#ifdef RPL_CONF_MCAST_LIFETIME
|
|
#define RPL_MCAST_LIFETIME RPL_CONF_MCAST_LIFETIME
|
|
#else
|
|
#define RPL_MCAST_LIFETIME 3
|
|
#endif
|
|
|
|
/*
|
|
* The ETX in the metric container is expressed as a fixed-point value
|
|
* whose integer part can be obtained by dividing the value by
|
|
* RPL_DAG_MC_ETX_DIVISOR.
|
|
*/
|
|
#define RPL_DAG_MC_ETX_DIVISOR 256
|
|
|
|
/* DIS related */
|
|
#define RPL_DIS_SEND 1
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* 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) \
|
|
do { \
|
|
if((counter) > RPL_LOLLIPOP_CIRCULAR_REGION) { \
|
|
(counter) = ((counter) + 1) & RPL_LOLLIPOP_MAX_VALUE; \
|
|
} else { \
|
|
(counter) = ((counter) + 1) & RPL_LOLLIPOP_CIRCULAR_REGION; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define RPL_LOLLIPOP_IS_INIT(counter) \
|
|
((counter) > RPL_LOLLIPOP_CIRCULAR_REGION)
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Logical representation of a DAG Information Object (DIO.) */
|
|
struct rpl_dio {
|
|
uip_ipaddr_t dag_id;
|
|
rpl_ocp_t ocp;
|
|
rpl_rank_t rank;
|
|
uint8_t grounded;
|
|
uint8_t mop;
|
|
uint8_t preference;
|
|
uint8_t version;
|
|
uint8_t instance_id;
|
|
uint8_t dtsn;
|
|
uint8_t dag_intdoubl;
|
|
uint8_t dag_intmin;
|
|
uint8_t dag_redund;
|
|
uint8_t default_lifetime;
|
|
uint16_t lifetime_unit;
|
|
rpl_rank_t dag_max_rankinc;
|
|
rpl_rank_t dag_min_hoprankinc;
|
|
rpl_prefix_t destination_prefix;
|
|
rpl_prefix_t prefix_info;
|
|
struct rpl_metric_container mc;
|
|
};
|
|
typedef struct rpl_dio rpl_dio_t;
|
|
|
|
#if RPL_CONF_STATS
|
|
/* Statistics for fault management. */
|
|
struct rpl_stats {
|
|
uint16_t mem_overflows;
|
|
uint16_t local_repairs;
|
|
uint16_t global_repairs;
|
|
uint16_t malformed_msgs;
|
|
uint16_t resets;
|
|
uint16_t parent_switch;
|
|
uint16_t forward_errors;
|
|
uint16_t loop_errors;
|
|
uint16_t loop_warnings;
|
|
uint16_t root_repairs;
|
|
};
|
|
typedef struct rpl_stats rpl_stats_t;
|
|
|
|
extern rpl_stats_t rpl_stats;
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
/* RPL macros. */
|
|
|
|
#if RPL_CONF_STATS
|
|
#define RPL_STAT(code) (code)
|
|
#else
|
|
#define RPL_STAT(code)
|
|
#endif /* RPL_CONF_STATS */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Instances */
|
|
extern rpl_instance_t instance_table[];
|
|
extern rpl_instance_t *default_instance;
|
|
|
|
/* ICMPv6 functions for RPL. */
|
|
void dis_output(uip_ipaddr_t *addr);
|
|
void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr);
|
|
void dao_output(rpl_parent_t *, uint8_t lifetime);
|
|
void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime);
|
|
void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t);
|
|
void rpl_icmp6_register_handlers(void);
|
|
|
|
/* RPL logic functions. */
|
|
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_instance_t *, rpl_parent_t *);
|
|
|
|
/* DAG object management. */
|
|
rpl_dag_t *rpl_alloc_dag(uint8_t, uip_ipaddr_t *);
|
|
rpl_instance_t *rpl_alloc_instance(uint8_t);
|
|
void rpl_free_dag(rpl_dag_t *);
|
|
void rpl_free_instance(rpl_instance_t *);
|
|
void rpl_purge_dags(void);
|
|
|
|
/* 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 *);
|
|
rpl_parent_t *rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr);
|
|
void rpl_nullify_parent(rpl_parent_t *);
|
|
void rpl_remove_parent(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_dag(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);
|
|
|
|
/* Objective function. */
|
|
rpl_of_t *rpl_find_of(rpl_ocp_t);
|
|
|
|
/* Timer functions. */
|
|
void rpl_schedule_dao(rpl_instance_t *);
|
|
void rpl_schedule_dao_immediately(rpl_instance_t *);
|
|
void rpl_schedule_unicast_dio_immediately(rpl_instance_t *instance);
|
|
void rpl_cancel_dao(rpl_instance_t *instance);
|
|
void rpl_schedule_probing(rpl_instance_t *instance);
|
|
|
|
void rpl_reset_dio_timer(rpl_instance_t *);
|
|
void rpl_reset_periodic_timer(void);
|
|
|
|
/* Route poisoning. */
|
|
void rpl_poison_routes(rpl_dag_t *, rpl_parent_t *);
|
|
|
|
|
|
rpl_instance_t *rpl_get_default_instance(void);
|
|
|
|
#endif /* RPL_PRIVATE_H */
|