1001 lines
24 KiB
C
1001 lines
24 KiB
C
/** @file
|
|
@brief RPL data handler
|
|
|
|
This is not to be included by the application.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2016 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef __RPL_H
|
|
#define __RPL_H
|
|
|
|
#include <kernel.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <net/net_ip.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_RPL)
|
|
|
|
#include "route.h"
|
|
|
|
#define NET_ICMPV6_RPL 155 /* RPL Control Message */
|
|
|
|
#define NET_RPL_DODAG_SOLICIT 0x00
|
|
#define NET_RPL_DODAG_INFO_OBJ 0x01
|
|
#define NET_RPL_DEST_ADV_OBJ 0x02
|
|
#define NET_RPL_DEST_ADV_OBJ_ACK 0x03
|
|
#define NET_RPL_SEC_DODAG_SOLICIT 0x80
|
|
#define NET_RPL_SEC_DODAG_INFO_OBJ 0x81
|
|
#define NET_RPL_SEC_DEST_ADV_OBJ 0x82
|
|
#define NET_RPL_SEC_DEST_ADV_OBJ_ACK 0x83
|
|
#define NET_RPL_CONSISTENCY_CHECK 0x8A
|
|
|
|
/* Routing Metric/Constraint Type, RFC 6551 ch 6.1 */
|
|
#define NET_RPL_MC_NONE 0 /* Local identifier for empty MC */
|
|
#define NET_RPL_MC_NSA 1 /* Node State and Attributes */
|
|
#define NET_RPL_MC_ENERGY 2 /* Node Energy */
|
|
#define NET_RPL_MC_HOPCOUNT 3 /* Hop Count */
|
|
#define NET_RPL_MC_THROUGHPUT 4 /* Throughput */
|
|
#define NET_RPL_MC_LATENCY 5 /* Latency */
|
|
#define NET_RPL_MC_LQL 6 /* Link Quality Level */
|
|
#define NET_RPL_MC_ETX 7 /* Expected Transmission Count */
|
|
#define NET_RPL_MC_LC 8 /* Link Color */
|
|
|
|
/* Routing Metric/Constraint Common Header Flag Field, RFC 6551, ch 6.3 */
|
|
#define NET_RPL_MC_FLAG_P BIT(5)
|
|
#define NET_RPL_MC_FLAG_C BIT(6)
|
|
#define NET_RPL_MC_FLAG_O BIT(7)
|
|
#define NET_RPL_MC_FLAG_R BIT(8)
|
|
|
|
/* Routing Metric/Constraint Common Header A Field, RFC 6551, ch 6.4 */
|
|
#define NET_RPL_MC_A_ADDITIVE 0
|
|
#define NET_RPL_MC_A_MAXIMUM 1
|
|
#define NET_RPL_MC_A_MINIMUM 2
|
|
#define NET_RPL_MC_A_MULTIPLICATIVE 3
|
|
|
|
/* Node type field, RFC 6551, ch 6.7 */
|
|
#define NET_RPL_MC_NODE_TYPE_MAINS 0
|
|
#define NET_RPL_MC_NODE_TYPE_BATTERY 1
|
|
#define NET_RPL_MC_NODE_TYPE_SCAVENGING 2
|
|
|
|
/* The bit index within the flags field of the RPL metric object energy
|
|
* structure.
|
|
*/
|
|
#define NET_RPL_MC_ENERGY_INCLUDED 3
|
|
#define NET_RPL_MC_ENERGY_TYPE 1
|
|
#define NET_RPL_MC_ENERGY_ESTIMATION 0
|
|
|
|
/* RPL control message options. */
|
|
#define NET_RPL_OPTION_PAD1 0
|
|
#define NET_RPL_OPTION_PADN 1
|
|
#define NET_RPL_OPTION_DAG_METRIC_CONTAINER 2
|
|
#define NET_RPL_OPTION_ROUTE_INFO 3
|
|
#define NET_RPL_OPTION_DAG_CONF 4
|
|
#define NET_RPL_OPTION_TARGET 5
|
|
#define NET_RPL_OPTION_TRANSIT 6
|
|
#define NET_RPL_OPTION_SOLICITED_INFO 7
|
|
#define NET_RPL_OPTION_PREFIX_INFO 8
|
|
#define NET_RPL_OPTION_TARGET_DESC 9
|
|
|
|
#define NET_RPL_MAX_RANK_INC (7 * CONFIG_NET_RPL_MIN_HOP_RANK_INC)
|
|
#define NET_RPL_INFINITE_RANK 0xffff
|
|
|
|
/* Rank of a root node. */
|
|
#define NET_RPL_ROOT_RANK(instance) ((instance)->min_hop_rank_inc)
|
|
|
|
#define NET_RPL_DAG_RANK(rank, instance) ((rank) / \
|
|
(instance)->min_hop_rank_inc)
|
|
|
|
/*
|
|
* The ETX in the metric container is expressed as a fixed-point value
|
|
* whose integer part can be obtained by dividing the value by
|
|
* NET_RPL_MC_ETX_DIVISOR.
|
|
*/
|
|
#define NET_RPL_MC_ETX_DIVISOR 256
|
|
|
|
/* DAG Mode of Operation */
|
|
#define NET_RPL_MOP_NO_DOWNWARD_ROUTES 0
|
|
#define NET_RPL_MOP_NON_STORING 1
|
|
#define NET_RPL_MOP_STORING_NO_MULTICAST 2
|
|
#define NET_RPL_MOP_STORING_MULTICAST 3
|
|
|
|
#if defined(CONFIG_NET_RPL_DEFAULT_INSTANCE)
|
|
#define NET_RPL_DEFAULT_INSTANCE CONFIG_NET_RPL_DEFAULT_INSTANCE
|
|
#else
|
|
#define NET_RPL_DEFAULT_INSTANCE 0x1e
|
|
#endif
|
|
|
|
#define NET_RPL_PARENT_FLAG_UPDATED 0x1
|
|
#define NET_RPL_PARENT_FLAG_LINK_METRIC_VALID 0x2
|
|
|
|
/* RPL IPv6 extension header option. */
|
|
#define NET_RPL_HDR_OPT_LEN 4
|
|
#define NET_RPL_HOP_BY_HOP_LEN (NET_RPL_HDR_OPT_LEN + 2 + 2)
|
|
#define NET_RPL_HDR_OPT_DOWN 0x80
|
|
#define NET_RPL_HDR_OPT_DOWN_SHIFT 7
|
|
#define NET_RPL_HDR_OPT_RANK_ERR 0x40
|
|
#define NET_RPL_HDR_OPT_RANK_ERR_SHIFT 6
|
|
#define NET_RPL_HDR_OPT_FWD_ERR 0x20
|
|
#define NET_RPL_HDR_OPT_FWD_ERR_SHIFT 5
|
|
|
|
/**
|
|
* RPL modes
|
|
*
|
|
* The RPL module can be in either of three modes: mesh mode
|
|
* (NET_RPL_MODE_MESH), feather mode (NET_RPL_MODE_FEATHER), and leaf mode
|
|
* (NET_RPL_MODE_LEAF). In mesh mode, nodes forward data for other nodes,
|
|
* and are reachable by others. In feather mode, nodes can forward
|
|
* data for other nodes, but are not reachable themselves. In leaf
|
|
* mode, nodes do not forward data for others, but are reachable by
|
|
* others.
|
|
*/
|
|
enum net_rpl_mode {
|
|
NET_RPL_MODE_MESH,
|
|
NET_RPL_MODE_FEATHER,
|
|
NET_RPL_MODE_LEAF,
|
|
};
|
|
|
|
/**
|
|
* Flag values in DAO message.
|
|
*/
|
|
#define NET_RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */
|
|
#define NET_RPL_DAO_D_FLAG 0x40 /* DODAG ID present */
|
|
|
|
#define NET_RPL_LOLLIPOP_MAX_VALUE 255
|
|
#define NET_RPL_LOLLIPOP_CIRCULAR_REGION 127
|
|
#define NET_RPL_LOLLIPOP_SEQUENCE_WINDOWS 16
|
|
|
|
static inline u8_t net_rpl_lollipop_init(void)
|
|
{
|
|
return NET_RPL_LOLLIPOP_MAX_VALUE -
|
|
NET_RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1;
|
|
}
|
|
|
|
static inline void net_rpl_lollipop_increment(u8_t *counter)
|
|
{
|
|
if (*counter > NET_RPL_LOLLIPOP_CIRCULAR_REGION) {
|
|
*counter = (*counter + 1) & NET_RPL_LOLLIPOP_MAX_VALUE;
|
|
} else {
|
|
*counter = (*counter + 1) & NET_RPL_LOLLIPOP_CIRCULAR_REGION;
|
|
}
|
|
}
|
|
|
|
static inline bool net_rpl_lollipop_is_init(u8_t counter)
|
|
{
|
|
return counter > NET_RPL_LOLLIPOP_CIRCULAR_REGION;
|
|
}
|
|
|
|
struct net_rpl_instance;
|
|
struct net_rpl_dag;
|
|
|
|
/**
|
|
* @brief DIO prefix suboption.
|
|
*/
|
|
struct net_rpl_prefix {
|
|
/** IPv6 address prefix */
|
|
struct in6_addr prefix;
|
|
|
|
/** Lifetime of the prefix */
|
|
u32_t lifetime;
|
|
|
|
/** Length of the prefix */
|
|
u8_t length;
|
|
|
|
/** Prefix flags */
|
|
u8_t flags;
|
|
};
|
|
|
|
/**
|
|
* @brief Node energy object, RFC 6551, ch 3.2
|
|
*/
|
|
struct net_rpl_node_energy_object {
|
|
/** Energy node flags */
|
|
u8_t flags;
|
|
|
|
/** Energy estimation */
|
|
u8_t estimation;
|
|
};
|
|
|
|
/**
|
|
* @brief DAG Metric Container. RFC 6551, ch 2.1
|
|
*/
|
|
struct net_rpl_metric_container {
|
|
/** Type of the container */
|
|
u8_t type;
|
|
|
|
/** Container flags */
|
|
u8_t flags;
|
|
|
|
/** Aggregated value (A field) */
|
|
u8_t aggregated;
|
|
|
|
/**
|
|
* Precedence of this Routing Metric/Constraint object relative
|
|
* to other objects in the container.
|
|
*/
|
|
u8_t precedence;
|
|
|
|
/** Length of the object body */
|
|
u8_t length;
|
|
|
|
/** Metric container information */
|
|
union metric_object {
|
|
struct net_rpl_node_energy_object energy;
|
|
u16_t etx;
|
|
} obj;
|
|
};
|
|
|
|
/**
|
|
* @brief Parent information.
|
|
*/
|
|
struct net_rpl_parent {
|
|
/** Used DAG */
|
|
struct net_rpl_dag *dag;
|
|
|
|
/** Used metric container */
|
|
struct net_rpl_metric_container mc;
|
|
|
|
/** When last transmit happened */
|
|
u32_t last_tx_time;
|
|
|
|
/** Rank of the parent */
|
|
u16_t rank;
|
|
|
|
/** Destination Advertisement Trigger Sequence Number */
|
|
u8_t dtsn;
|
|
|
|
/** Parent flags */
|
|
u8_t flags;
|
|
};
|
|
|
|
/**
|
|
* @brief Directed Acyclic Graph (DAG)
|
|
*/
|
|
struct net_rpl_dag {
|
|
/** DAG id */
|
|
struct in6_addr dag_id;
|
|
|
|
/** What is the preferred parent. */
|
|
struct net_rpl_parent *preferred_parent;
|
|
|
|
/** IPv6 prefix information */
|
|
struct net_rpl_prefix prefix_info;
|
|
|
|
/** Used RPL instance */
|
|
struct net_rpl_instance *instance;
|
|
|
|
/** Minimum rank */
|
|
u16_t min_rank;
|
|
|
|
/** DAG rank */
|
|
u16_t rank;
|
|
|
|
/** DAG version. */
|
|
u8_t version;
|
|
|
|
/** DODAG preference. */
|
|
u8_t preference : 3;
|
|
|
|
/** Is this DAG used or not. */
|
|
u8_t is_used : 1;
|
|
|
|
/** Is DAG grounded or floating. */
|
|
u8_t is_grounded : 1;
|
|
|
|
/** Is DAG joined or not. */
|
|
u8_t is_joined : 1;
|
|
|
|
u8_t _unused : 2;
|
|
};
|
|
|
|
/**
|
|
* @brief Get related neighbor information from parent pointer.
|
|
*
|
|
* @param data Pointer to parent.
|
|
*
|
|
* @return Neighbor pointer if found, NULL if neighbor is not found.
|
|
*/
|
|
struct net_nbr *net_rpl_get_nbr(struct net_rpl_parent *data);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) reset.
|
|
*
|
|
* @details Reset the OF state for a specific DAG. This function is called when
|
|
* doing a global repair on the DAG.
|
|
*
|
|
* @param dag Pointer to DAG object
|
|
*/
|
|
extern void net_rpl_of_reset(struct net_rpl_dag *dag);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) neighbor link callback.
|
|
*
|
|
* @details Receives link-layer neighbor information. The etx parameter
|
|
* specifies the current ETX(estimated transmissions) for the neighbor.
|
|
*
|
|
* @param iface Network interface
|
|
* @param parent Parent of the neighbor
|
|
* @param status Transmission status
|
|
* @param ext Estimated transmissions value
|
|
*
|
|
* @return 0 if ok, < 0 if error
|
|
*/
|
|
extern int net_rpl_of_neighbor_link_cb(struct net_if *iface,
|
|
struct net_rpl_parent *parent,
|
|
int status, int etx);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) get best parent.
|
|
*
|
|
* @details Compares two parents and returns the best one.
|
|
*
|
|
* @param iface Network interface.
|
|
* @param parentA First parent.
|
|
* @param parentB Second parent.
|
|
*
|
|
* @return Best parent is returned.
|
|
*/
|
|
extern struct net_rpl_parent *
|
|
net_rpl_of_best_parent(struct net_if *iface,
|
|
struct net_rpl_parent *parentA,
|
|
struct net_rpl_parent *parentB);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) get best DAG.
|
|
*
|
|
* @details Compares two DAGs and returns the best one.
|
|
*
|
|
* @param dagA First DAG.
|
|
* @param dagB Second DAG.
|
|
*
|
|
* @return Best DAG.
|
|
*/
|
|
extern struct net_rpl_dag *net_rpl_of_best_dag(struct net_rpl_dag *dagA,
|
|
struct net_rpl_dag *dagB);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) calculate rank.
|
|
*
|
|
* @details Calculates a rank value using the parent rank and a base rank.
|
|
* If parent is not set, the OF selects a default increment that is
|
|
* added to the base rank. Otherwise, the OF uses information known
|
|
* about parent to select an increment to the base rank.
|
|
*/
|
|
extern u16_t net_rpl_of_calc_rank(struct net_rpl_parent *parent,
|
|
u16_t rank);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) update metric container.
|
|
*
|
|
* @details Updates the metric container for outgoing DIOs in a certain DAG.
|
|
* If the OF of the DAG does not use metric containers, the function
|
|
* should set the object type to NET_RPL_MC_NONE.
|
|
*
|
|
* @param instance Pointer to RPL instance.
|
|
*/
|
|
extern int net_rpl_of_update_mc(struct net_rpl_instance *instance);
|
|
|
|
/**
|
|
* @brief RPL object function (OF) objective code point used.
|
|
*
|
|
* @details Check if we support desired objective function.
|
|
*
|
|
* @param ocp Objective Code Point value
|
|
*
|
|
* @return true if OF is supported, false otherwise.
|
|
*/
|
|
extern bool net_rpl_of_find(u16_t ocp);
|
|
|
|
/**
|
|
* @brief Return RPL object function (OF) objective code point used.
|
|
*
|
|
* @return OCP (Objective Code Point) value used.
|
|
*/
|
|
extern u16_t net_rpl_of_get(void);
|
|
|
|
/**
|
|
* @brief RPL instance structure
|
|
*
|
|
* Describe RPL instance.
|
|
*/
|
|
struct net_rpl_instance {
|
|
/** Routing metric information */
|
|
struct net_rpl_metric_container mc;
|
|
|
|
/** All the DAGs for this RPL instance */
|
|
struct net_rpl_dag dags[CONFIG_NET_RPL_MAX_DAG_PER_INSTANCE];
|
|
|
|
#if defined(CONFIG_NET_RPL_PROBING)
|
|
/** When next probe message will be sent. */
|
|
struct k_delayed_work probing_timer;
|
|
#endif /* CONFIG_NET_RPL_PROBING */
|
|
|
|
/** DODAG Information Object timer. */
|
|
struct k_delayed_work dio_timer;
|
|
|
|
/** Destination Advertisement Object timer. */
|
|
struct k_delayed_work dao_timer;
|
|
|
|
/** DAO lifetime timer. */
|
|
struct k_delayed_work dao_lifetime_timer;
|
|
|
|
#if defined(CONFIG_NET_RPL_DAO_ACK)
|
|
/** DAO retransmit timer */
|
|
struct k_delayed_work dao_retransmit_timer;
|
|
|
|
/** DAO number of retransmissions */
|
|
u8_t dao_transmissions;
|
|
#endif
|
|
|
|
/** Network interface to send DAO */
|
|
struct net_if *iface;
|
|
|
|
/** Current DAG in use */
|
|
struct net_rpl_dag *current_dag;
|
|
|
|
/** Current default router information */
|
|
struct net_if_router *default_route;
|
|
|
|
/** Amount of time for completion of dio interval */
|
|
u32_t dio_next_delay;
|
|
|
|
/** Objective Code Point (Used objective function) */
|
|
u16_t ocp;
|
|
|
|
/** MaxRankIncrease, RFC 6550, ch 6.7.6 */
|
|
u16_t max_rank_inc;
|
|
|
|
/** MinHopRankIncrease, RFC 6550, ch 6.7.6 */
|
|
u16_t min_hop_rank_inc;
|
|
|
|
/**
|
|
* Provides the unit in seconds that is used to express route
|
|
* lifetimes in RPL. For very stable networks, it can be hours
|
|
* to days. RFC 6550, ch 6.7.6
|
|
*/
|
|
u16_t lifetime_unit;
|
|
|
|
#if defined(CONFIG_NET_STATISTICS_RPL)
|
|
/** Number of DIO intervals for this RPL instance. */
|
|
u16_t dio_intervals;
|
|
|
|
/** Number of DIOs sent for this RPL instance. */
|
|
u16_t dio_send_pkt;
|
|
|
|
/** Number of DIOs received for this RPL instance. */
|
|
u16_t dio_recv_pkt;
|
|
#endif /* CONFIG_NET_STATISTICS_RPL */
|
|
|
|
/**
|
|
* This is the lifetime that is used as default for all RPL routes.
|
|
* It is expressed in units of Lifetime Units, e.g., the default
|
|
* lifetime in seconds is (Default Lifetime) * (Lifetime Unit)
|
|
* RFC 6550, ch 6.7.6
|
|
*/
|
|
u8_t default_lifetime;
|
|
|
|
/** Instance ID of this RPL instance */
|
|
u8_t instance_id;
|
|
|
|
/** Destination Advertisement Trigger Sequence Number */
|
|
u8_t dtsn;
|
|
|
|
/** Mode of operation */
|
|
u8_t mop;
|
|
|
|
/** DIOIntervalDoublings, RFC 6550, ch 6.7.6 */
|
|
u8_t dio_interval_doublings;
|
|
|
|
/** DIOIntervalMin, RFC 6550, ch 6.7.6 */
|
|
u8_t dio_interval_min;
|
|
|
|
/** Current DIO interval */
|
|
u8_t dio_interval_current;
|
|
|
|
/** DIORedundancyConstant, ch 6.7.6 */
|
|
u8_t dio_redundancy;
|
|
|
|
/** Current number of DIOs received (temp var) */
|
|
u8_t dio_counter;
|
|
|
|
/** Keep track of whether we can send DIOs or not (true if we can send)
|
|
*/
|
|
bool dio_send;
|
|
|
|
/** Is this RPL instance used or not */
|
|
bool is_used;
|
|
|
|
/** Is DAO timer active or not. */
|
|
bool dao_timer_active;
|
|
|
|
/** Is DAO lifetime timer active or not. */
|
|
bool dao_lifetime_timer_active;
|
|
};
|
|
|
|
/**
|
|
* @brief RPL DIO structure
|
|
*
|
|
* Describe RPL DAG Information Object.
|
|
*/
|
|
struct net_rpl_dio {
|
|
/** Routing metric information */
|
|
struct net_rpl_metric_container mc;
|
|
|
|
/** DAG id */
|
|
struct in6_addr dag_id;
|
|
|
|
/** IPv6 prefix information */
|
|
struct net_rpl_prefix prefix_info;
|
|
|
|
/** IPv6 destination prefix */
|
|
struct net_rpl_prefix destination_prefix;
|
|
|
|
/** Objective Code Point (OF being used) */
|
|
u16_t ocp;
|
|
|
|
/** Current rank */
|
|
u16_t rank;
|
|
|
|
/** MaxRankIncrease, RFC 6550, ch 6.7.6 */
|
|
u16_t max_rank_inc;
|
|
|
|
/** MinHopRankIncrease, RFC 6550, ch 6.7.6 */
|
|
u16_t min_hop_rank_inc;
|
|
/**
|
|
* Provides the unit in seconds that is used to express route
|
|
* lifetimes in RPL. For very stable networks, it can be hours
|
|
* to days. RFC 6550, ch 6.7.6
|
|
*/
|
|
u16_t lifetime_unit;
|
|
|
|
/**
|
|
* This is the lifetime that is used as default for all RPL routes.
|
|
* It is expressed in units of Lifetime Units, e.g., the default
|
|
* lifetime in seconds is (Default Lifetime) * (Lifetime Unit)
|
|
* RFC 6550, ch 6.7.6
|
|
*/
|
|
u8_t default_lifetime;
|
|
|
|
/** Instance ID of this RPL instance */
|
|
u8_t instance_id;
|
|
|
|
/** Destination Advertisement Trigger Sequence Number */
|
|
u8_t dtsn;
|
|
|
|
/** Mode of operation */
|
|
u8_t mop;
|
|
|
|
/** DAG interval doublings */
|
|
u8_t dag_interval_doublings;
|
|
|
|
/** DAG interval min */
|
|
u8_t dag_interval_min;
|
|
|
|
/** DAG interval */
|
|
u8_t dag_interval_current;
|
|
|
|
/** DAG redundancy constant */
|
|
u8_t dag_redundancy;
|
|
|
|
/** Is this DAG grounded or floating */
|
|
u8_t grounded;
|
|
|
|
/** DODAG preference */
|
|
u8_t preference;
|
|
|
|
/** DODAG version number */
|
|
u8_t version;
|
|
};
|
|
|
|
/**
|
|
* @brief RPL route information source
|
|
*/
|
|
enum net_rpl_route_source {
|
|
NET_RPL_ROUTE_INTERNAL,
|
|
NET_RPL_ROUTE_UNICAST_DAO,
|
|
NET_RPL_ROUTE_MULTICAST_DAO,
|
|
NET_RPL_ROUTE_DIO,
|
|
};
|
|
|
|
/**
|
|
* @brief RPL route entry
|
|
*
|
|
* Stores extra information for RPL route.
|
|
*/
|
|
struct net_rpl_route_entry {
|
|
/** Dag info for this route */
|
|
struct net_rpl_dag *dag;
|
|
|
|
/** Lifetime for this route entry (in seconds) */
|
|
u32_t lifetime;
|
|
|
|
/** Where this route came from */
|
|
enum net_rpl_route_source route_source;
|
|
|
|
/** No-Path target option with lifetime 0 received (true) or (false) */
|
|
bool no_path_received;
|
|
};
|
|
|
|
/**
|
|
* The extra data size is used in route.h to determine how much extra
|
|
* space to allocate for RPL specific data.
|
|
*/
|
|
#define NET_ROUTE_EXTRA_DATA_SIZE sizeof(struct net_rpl_route_entry)
|
|
|
|
/**
|
|
* @brief Check if the IPv6 address is a RPL multicast address.
|
|
*
|
|
* @param addr IPv6 address
|
|
*
|
|
* @return True if address is RPL multicast address, False otherwise.
|
|
*/
|
|
static inline bool net_rpl_is_ipv6_addr_mcast(const struct in6_addr *addr)
|
|
{
|
|
return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
|
|
UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
|
|
UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00000000 &&
|
|
UNALIGNED_GET(&addr->s6_addr32[3]) == htonl(0x0000001a);
|
|
}
|
|
|
|
/**
|
|
* @brief Create RPL IPv6 multicast address FF02::1a
|
|
*
|
|
* @param addr IPv6 address.
|
|
*
|
|
* @return Pointer to given IPv6 address.
|
|
*/
|
|
static inline
|
|
struct in6_addr *net_rpl_create_mcast_address(struct in6_addr *addr)
|
|
{
|
|
addr->s6_addr[0] = 0xFF;
|
|
addr->s6_addr[1] = 0x02;
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[1]);
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[2]);
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[3]);
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[4]);
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[5]);
|
|
UNALIGNED_PUT(0, &addr->s6_addr16[6]);
|
|
addr->s6_addr[14] = 0;
|
|
addr->s6_addr[15] = 0x1a;
|
|
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
* @brief Return information whether the DAG is in use right now.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*
|
|
* @return true if in use, false otherwise
|
|
*/
|
|
static inline bool net_rpl_dag_is_used(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
return !!dag->is_used;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the DAG as not in use.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*/
|
|
static inline void net_rpl_dag_set_not_used(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
dag->is_used = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the DAG as in use.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*/
|
|
static inline void net_rpl_dag_set_used(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
dag->is_used = 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Return information whether the DAG is grounded or floating.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*
|
|
* @return true if grounded, false if floating
|
|
*/
|
|
static inline bool net_rpl_dag_is_grounded(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
return !!dag->is_grounded;
|
|
}
|
|
|
|
/**
|
|
* @brief Set DAG information whether it is grounded or floating.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*/
|
|
static inline void net_rpl_dag_set_grounded_status(struct net_rpl_dag *dag,
|
|
bool grounded)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
dag->is_grounded = grounded;
|
|
}
|
|
|
|
/**
|
|
* @brief Return information whether the DAG is joined or not.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*
|
|
* @return true if joined, false otherwise
|
|
*/
|
|
static inline bool net_rpl_dag_is_joined(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
return !!dag->is_joined;
|
|
}
|
|
|
|
/**
|
|
* @brief Mark DAG as joined.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*/
|
|
static inline void net_rpl_dag_join(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
dag->is_joined = 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Mark DAG as joined.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*/
|
|
static inline void net_rpl_dag_unjoin(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
dag->is_joined = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Get preference for this DAG.
|
|
*
|
|
* @details This function returns the preference of the dag.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
*
|
|
* @return preference value
|
|
*/
|
|
static inline
|
|
u8_t net_rpl_dag_get_preference(struct net_rpl_dag *dag)
|
|
{
|
|
NET_ASSERT(dag);
|
|
|
|
return dag->preference;
|
|
}
|
|
|
|
/**
|
|
* @brief Set preference for this DAG.
|
|
*
|
|
* @details This function sets the preference of the dag.
|
|
*
|
|
* @param dag Pointer to DAG.
|
|
* @param preference New preference value.
|
|
*/
|
|
static inline
|
|
void net_rpl_dag_set_preference(struct net_rpl_dag *dag,
|
|
u8_t preference)
|
|
{
|
|
NET_ASSERT(dag && preference <= 8);
|
|
|
|
dag->preference = preference;
|
|
}
|
|
|
|
/**
|
|
* @typedef net_rpl_join_callback_t
|
|
* @brief Callback for evaluating if this is a network to join or not.
|
|
* @param dio Pointer to DIO.
|
|
* @return True if the network is to be joined, false otherwise.
|
|
*/
|
|
typedef bool (*net_rpl_join_callback_t)(struct net_rpl_dio *dio);
|
|
|
|
/**
|
|
* @brief Register a callback that determines if the network is to be
|
|
* joined or not.
|
|
*
|
|
* @param cb Callback function
|
|
*/
|
|
void net_rpl_set_join_callback(net_rpl_join_callback_t cb);
|
|
|
|
/**
|
|
* @brief Send a DODAG Information Solicitation message.
|
|
*
|
|
* @param dst Destination IPv6 address.
|
|
* @param iface Interface to send the message to.
|
|
*
|
|
* @return 0 message was sent ok, <0 otherwise
|
|
*/
|
|
int net_rpl_dis_send(struct in6_addr *dst, struct net_if *iface);
|
|
|
|
/**
|
|
* @brief Send a Destination Advertisement Object message.
|
|
*
|
|
* @param iface Network interface to use, this can be set to NULL in which
|
|
* case the function can try to figure it out itself.
|
|
* @param parent Pointer to parent information.
|
|
* @param prefix IPv6 address
|
|
* @param lifetime Lifetime of the advertisement.
|
|
*
|
|
* @return 0 message was sent ok, <0 otherwise
|
|
*/
|
|
int net_rpl_dao_send(struct net_if *iface,
|
|
struct net_rpl_parent *parent,
|
|
struct in6_addr *prefix,
|
|
u8_t lifetime);
|
|
|
|
/**
|
|
* @brief Send a DODAG Information Object message.
|
|
*
|
|
* @param iface Network interface to use, this can be set to NULL in which
|
|
* case the function can try to figure it out itself.
|
|
* @param instance Pointer to instance object.
|
|
* @param src IPv6 source address.
|
|
* @param dst IPv6 destination address.
|
|
*
|
|
* @return 0 message was sent ok, <0 otherwise
|
|
*/
|
|
int net_rpl_dio_send(struct net_if *iface,
|
|
struct net_rpl_instance *instance,
|
|
struct in6_addr *src,
|
|
struct in6_addr *dst);
|
|
|
|
/**
|
|
* @brief Set the root DAG.
|
|
*
|
|
* @param iface Network interface to use.
|
|
* @param instance Pointer to instance object.
|
|
* @param dag_id IPv6 address of the DAG.
|
|
*
|
|
* @return DAG object or NULL if creation failed.
|
|
*/
|
|
struct net_rpl_dag *net_rpl_set_root(struct net_if *iface,
|
|
u8_t instance_id,
|
|
struct in6_addr *dag_id);
|
|
|
|
/**
|
|
* @brief Get first available DAG.
|
|
*
|
|
* @return First available DAG or NULL if none found.
|
|
*/
|
|
struct net_rpl_dag *net_rpl_get_any_dag(void);
|
|
|
|
/**
|
|
* @brief Set IPv6 prefix we are using.
|
|
*
|
|
* @param iface Network interface in use.
|
|
* @param dag DAG in use.
|
|
* @param prefix IPv6 prefix we are using.
|
|
* @param prefix_len IPv6 prefix length.
|
|
*
|
|
* @return True if prefix could be set, false otherwise.
|
|
*/
|
|
bool net_rpl_set_prefix(struct net_if *iface,
|
|
struct net_rpl_dag *dag,
|
|
struct in6_addr *prefix,
|
|
u8_t prefix_len);
|
|
|
|
/**
|
|
* @brief Do global repair for this route.
|
|
*
|
|
* @param route IPv6 route entry.
|
|
*/
|
|
void net_rpl_global_repair(struct net_route_entry *route);
|
|
|
|
/**
|
|
* @brief Update RPL headers in IPv6 packet.
|
|
*
|
|
* @param pkt Network packet.
|
|
* @param addr IPv6 address of next hop host.
|
|
*
|
|
* @return 0 if ok, < 0 if error
|
|
*/
|
|
int net_rpl_update_header(struct net_pkt *pkt, struct in6_addr *addr);
|
|
|
|
/**
|
|
* @brief Verify RPL header in IPv6 packet.
|
|
*
|
|
* @param pkt Network packet fragment list.
|
|
* @param frag Current network buffer fragment.
|
|
* @param offset Where the RPL header starts in the packet
|
|
* @param pos How long the RPL header was, this is returned to the caller.
|
|
* @param out result True if ok, false if error
|
|
*
|
|
* @return frag Returns the fragment where this call finished reading.
|
|
*/
|
|
struct net_buf *net_rpl_verify_header(struct net_pkt *pkt, struct net_buf *frag,
|
|
u16_t offset, u16_t *pos,
|
|
bool *result);
|
|
|
|
/**
|
|
* @brief Insert RPL extension header to IPv6 packet.
|
|
*
|
|
* @param pkt Network packet.
|
|
*
|
|
* @return 0 if ok, <0 if error.
|
|
*/
|
|
int net_rpl_insert_header(struct net_pkt *pkt);
|
|
|
|
/**
|
|
* @brief Revert RPL extension header to IPv6 packet.
|
|
* Revert flags, instance ID and sender rank in the packet.
|
|
*
|
|
* @param pkt Network packet.
|
|
* @param offset Where the HBH header starts in the packet
|
|
* @param pos How long the RPL header was, this is returned to the caller.
|
|
*
|
|
* @return 0 if ok, <0 if error.
|
|
*/
|
|
int net_rpl_revert_header(struct net_pkt *pkt, u16_t offset, u16_t *pos);
|
|
|
|
/**
|
|
* @brief Get parent IPv6 address.
|
|
*
|
|
* @param iface Network interface
|
|
* @param parent Parent pointer
|
|
*
|
|
* @return Parent IPv6 address, or NULL if no such parent.
|
|
*/
|
|
struct in6_addr *net_rpl_get_parent_addr(struct net_if *iface,
|
|
struct net_rpl_parent *parent);
|
|
|
|
/**
|
|
* @brief Set the RPL mode (mesh or leaf) of this node.
|
|
*
|
|
* @param new_mode New RPL mode. Value is either NET_RPL_MODE_MESH,
|
|
* NET_RPL_MODE_FEATHER or NET_RPL_MODE_LEAF. The NET_RPL_MODE_MESH is
|
|
* the default mode.
|
|
*/
|
|
void net_rpl_set_mode(enum net_rpl_mode new_mode);
|
|
|
|
/**
|
|
* @brief Get the RPL mode (mesh or leaf) of this node.
|
|
*
|
|
* @return Current RPL mode.
|
|
*/
|
|
enum net_rpl_mode net_rpl_get_mode(void);
|
|
|
|
/**
|
|
* @brief Get the default RPL instance.
|
|
*
|
|
* @return Current default RPL instance.
|
|
*/
|
|
struct net_rpl_instance *net_rpl_get_default_instance(void);
|
|
|
|
void net_rpl_init(void);
|
|
#else
|
|
#define net_rpl_init(...)
|
|
#define net_rpl_global_repair(...)
|
|
#define net_rpl_update_header(...) 0
|
|
#endif /* CONFIG_NET_RPL */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __RPL_H */
|