/* * 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. * */ /** * \addtogroup rpl-lite * @{ * * \file * RPL types and macros * \author * Joakim Eriksson & Nicolas Tsiftes * Simon Duquennoy * */ #ifndef RPL_TYPES_H #define RPL_TYPES_H /********** Macros **********/ /* Multicast address: create and compare */ /** \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) /** \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 Compute lifetime, accounting for the lifetime unit */ #define RPL_LIFETIME(lifetime) \ (((lifetime) == RPL_INFINITE_LIFETIME) ? \ RPL_ROUTE_INFINITE_LIFETIME : \ (unsigned long)curr_instance.lifetime_unit * (lifetime)) /** \brief Rank of a root node. */ #define ROOT_RANK curr_instance.min_hoprankinc /** \brief Return DAG RANK as per RFC 6550 (rank divided by min_hoprankinc) */ #define DAG_RANK(fixpt_rank) ((fixpt_rank) / curr_instance.min_hoprankinc) #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) /********** Data structures and types **********/ typedef uint16_t rpl_rank_t; typedef uint16_t rpl_ocp_t; /*---------------------------------------------------------------------------*/ /** \brief Structure for RPL energy metric. */ struct rpl_metric_object_energy { uint8_t flags; uint8_t energy_est; }; /** \brief Logical representation of a DAG Metric Container. */ struct rpl_metric_container { uint8_t type; uint8_t flags; uint8_t aggr; uint8_t prec; uint8_t length; union metric_object { struct rpl_metric_object_energy energy; uint16_t etx; } obj; }; typedef struct rpl_metric_container rpl_metric_container_t; /** \brief RPL prefix information */ struct rpl_prefix { uip_ipaddr_t prefix; uint32_t lifetime; uint8_t length; uint8_t flags; }; typedef struct rpl_prefix rpl_prefix_t; /** \brief All information related to a RPL neighbor */ struct rpl_nbr { clock_time_t better_parent_since; /* The neighbor has been a possible replacement for our preferred parent consistently since 'parent_since'. Currently used by MRHOF only. */ #if RPL_WITH_MC rpl_metric_container_t mc; #endif /* RPL_WITH_MC */ rpl_rank_t rank; uint8_t dtsn; }; typedef struct rpl_nbr rpl_nbr_t; /*---------------------------------------------------------------------------*/ /** * \brief API for RPL objective functions (OF) * * - reset(dag) Resets the objective function state for a specific DAG. This function is * called when doing a global repair on the DAG. * - nbr_link_metric(n) Returns the link metric of a neighbor * - nbr_has_usable_link(n) Returns 1 iff the neighbor has a usable link as defined by the OF * - nbr_is_acceptable_parent(n) Returns 1 iff the neighbor has a usable rank/link as defined by the OF * - nbr_path_cost(n) Returns the path cost of a neighbor * - rank_via_nbr(n) Returns our rank if we select a given neighbor as preferred parent * - best_parent(n1, n2) Compares two neighbors and returns the best one, according to the OF. * - update_metric_container() Updated the DAG metric container from the current OF state */ struct rpl_of { void (*reset)(void); uint16_t (*nbr_link_metric)(rpl_nbr_t *); int (*nbr_has_usable_link)(rpl_nbr_t *); int (*nbr_is_acceptable_parent)(rpl_nbr_t *); uint16_t (*nbr_path_cost)(rpl_nbr_t *); rpl_rank_t (*rank_via_nbr)(rpl_nbr_t *); rpl_nbr_t *(*best_parent)(rpl_nbr_t *, rpl_nbr_t *); void (*update_metric_container)(void); rpl_ocp_t ocp; }; typedef struct rpl_of rpl_of_t; /*---------------------------------------------------------------------------*/ /** \brief RPL DAG states*/ enum rpl_dag_state { DAG_INITIALIZED, DAG_JOINED, DAG_REACHABLE, DAG_POISONING }; /** \brief RPL DAG structure */ struct rpl_dag { uip_ipaddr_t dag_id; rpl_prefix_t prefix_info; rpl_nbr_t *preferred_parent; rpl_rank_t lowest_rank; /* The lowest rank seen in the current version */ rpl_rank_t rank; /* The current rank */ rpl_rank_t last_advertised_rank; /* The last rank advertised in a multicast-DIO */ uint32_t lifetime; uint8_t version; uint8_t grounded; uint8_t preference; uint8_t dio_intcurrent; /* Current DIO interval */ uint8_t dio_send; /* internal trickle timer state: do we need to send a DIO at the next wakeup? */ uint8_t dio_counter; /* internal trickle timer state: redundancy counter */ uint8_t dao_last_seqno; /* the node's last sent DAO seqno */ uint8_t dao_last_acked_seqno; /* the last seqno we got an ACK for */ uint8_t dao_transmissions; /* the number of transmissions for the current DAO */ enum rpl_dag_state state; /* Timers */ clock_time_t dio_next_delay; /* delay for completion of dio interval */ struct ctimer state_update; struct ctimer leave; struct ctimer dio_timer; struct ctimer unicast_dio_timer; struct ctimer dao_timer; rpl_nbr_t *unicast_dio_target; #if RPL_WITH_PROBING struct ctimer probing_timer; rpl_nbr_t *urgent_probing_target; #endif /* RPL_WITH_PROBING */ #if RPL_WITH_DAO_ACK uip_ipaddr_t dao_ack_target; uint16_t dao_ack_sequence; struct ctimer dao_ack_timer; #endif /* RPL_WITH_DAO_ACK */ }; typedef struct rpl_dag rpl_dag_t; /*---------------------------------------------------------------------------*/ /** \brief RPL instance structure */ struct rpl_instance { rpl_metric_container_t mc; /* Metric container. Set to MC_NONE when no mc is used */ rpl_of_t *of; /* The objective function */ uint8_t used; uint8_t instance_id; uint8_t mop; /* Mode of operation */ uint8_t dtsn_out; uint8_t dio_intdoubl; uint8_t dio_intmin; uint8_t dio_redundancy; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; uint8_t default_lifetime; uint16_t lifetime_unit; /* lifetime in seconds = lifetime_unit * default_lifetime */ rpl_dag_t dag; /* We support only one dag */ }; typedef struct rpl_instance rpl_instance_t; /** @} */ #endif /* RPL_TYPES_H */