mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 06:23:53 +01:00
Merge pull request #3737 from cgundogan/pr/rpl/instance_dodag_refactoring
rpl: refactoring of instances and dodags
This commit is contained in:
commit
054bca637c
@ -319,6 +319,14 @@ static inline bool GNRC_RPL_COUNTER_GREATER_THAN(uint8_t A, uint8_t B)
|
||||
*/
|
||||
#define GNRC_RPL_LIFETIME_UPDATE_STEP (2)
|
||||
|
||||
/**
|
||||
* @brief Rank part of the DODAG
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6550#section-3.5.1">
|
||||
* RFC 6550, section 3.5.1, Rank Comparison (DAGRank())
|
||||
* </a>
|
||||
*/
|
||||
#define DAGRANK(rank,mhri) (rank/mhri)
|
||||
|
||||
/**
|
||||
* @name Global / Local instance id masks
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6550#section-5.1">
|
||||
@ -357,45 +365,45 @@ kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid);
|
||||
* @param[in] local_inst_id Flag indicating whether a local or global instance id
|
||||
* should be generatad
|
||||
*
|
||||
* @return Pointer to the new DODAG, on success.
|
||||
* @return Pointer to the new RPL Instance, on success.
|
||||
* @return NULL, otherwise.
|
||||
*/
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id, bool gen_inst_id,
|
||||
bool local_inst_id);
|
||||
gnrc_rpl_instance_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
||||
bool gen_inst_id, bool local_inst_id);
|
||||
|
||||
/**
|
||||
* @brief Send a DIO of the @p dodag to the @p destination.
|
||||
* @brief Send a DIO of the @p instance to the @p destination.
|
||||
*
|
||||
* @param[in] dodag Pointer to the DODAG.
|
||||
* @param[in] instance Pointer to the RPL instance.
|
||||
* @param[in] destination IPv6 addres of the destination.
|
||||
*/
|
||||
void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination);
|
||||
void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination);
|
||||
|
||||
/**
|
||||
* @brief Send a DIS of the @p dodag to the @p destination.
|
||||
* @brief Send a DIS of the @p instace to the @p destination.
|
||||
*
|
||||
* @param[in] dodag Pointer to the DODAG, optional.
|
||||
* @param[in] instance Pointer to the RPL instance, optional.
|
||||
* @param[in] destination IPv6 addres of the destination.
|
||||
*/
|
||||
void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination);
|
||||
void gnrc_rpl_send_DIS(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination);
|
||||
|
||||
/**
|
||||
* @brief Send a DAO of the @p dodag to the @p destination.
|
||||
*
|
||||
* @param[in] dodag Pointer to the DODAG.
|
||||
* @param[in] instance Pointer to the instance.
|
||||
* @param[in] destination IPv6 addres of the destination.
|
||||
* @param[in] lifetime Lifetime of the route to announce.
|
||||
*/
|
||||
void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_t lifetime);
|
||||
void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination, uint8_t lifetime);
|
||||
|
||||
/**
|
||||
* @brief Send a DAO-ACK of the @p dodag to the @p destination.
|
||||
* @brief Send a DAO-ACK of the @p instance to the @p destination.
|
||||
*
|
||||
* @param[in] dodag Pointer to the DODAG, optional.
|
||||
* @param[in] instance Pointer to the RPL instance.
|
||||
* @param[in] destination IPv6 addres of the destination.
|
||||
* @param[in] seq Sequence number to be acknowledged.
|
||||
*/
|
||||
void gnrc_rpl_send_DAO_ACK(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_t seq);
|
||||
void gnrc_rpl_send_DAO_ACK(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination, uint8_t seq);
|
||||
|
||||
/**
|
||||
* @brief Parse a DIS.
|
||||
@ -448,16 +456,17 @@ void gnrc_rpl_delay_dao(gnrc_rpl_dodag_t *dodag);
|
||||
void gnrc_rpl_long_delay_dao(gnrc_rpl_dodag_t *dodag);
|
||||
|
||||
/**
|
||||
* @brief Creation of a RPL DODAG as root. Creates a new instance if necessary.
|
||||
* @brief Create a new RPL instance and RPL DODAG.
|
||||
*
|
||||
* @param[in] instance_id Id of the instance
|
||||
* @param[in] dodag_id Id of the DODAG
|
||||
* @param[in] mop Mode of Operation
|
||||
*
|
||||
* @return Pointer to the new DODAG, on success.
|
||||
* @return Pointer to the new RPL instance, on success.
|
||||
* @return NULL, otherwise.
|
||||
*/
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_id, uint8_t mop);
|
||||
gnrc_rpl_instance_t *gnrc_rpl_root_instance_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
||||
uint8_t mop);
|
||||
|
||||
/**
|
||||
* @brief Send a control message
|
||||
|
||||
@ -39,13 +39,6 @@ extern "C" {
|
||||
#define GNRC_RPL_INSTANCES_NUMOF (2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of RPL dodags
|
||||
*/
|
||||
#ifndef GNRC_RPL_DODAGS_NUMOF
|
||||
#define GNRC_RPL_DODAGS_NUMOF (4)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of RPL parents
|
||||
*/
|
||||
@ -58,11 +51,6 @@ extern "C" {
|
||||
*/
|
||||
extern gnrc_rpl_instance_t gnrc_rpl_instances[GNRC_RPL_INSTANCES_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief RPL DODAG table
|
||||
*/
|
||||
extern gnrc_rpl_dodag_t gnrc_rpl_dodags[GNRC_RPL_DODAGS_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief RPL parent table
|
||||
*/
|
||||
@ -110,27 +98,15 @@ bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst);
|
||||
gnrc_rpl_instance_t *gnrc_rpl_instance_get(uint8_t instance_id);
|
||||
|
||||
/**
|
||||
* @brief Add a new RPL DODAG with the id @p dodag_id to the instance @p instance.
|
||||
* @brief Initialize a new RPL DODAG with the id @p dodag_id for the instance @p instance.
|
||||
*
|
||||
* @param[in] instance Pointer to the instance to add the DODAG to
|
||||
* @param[in] dodag_id The DODAG-ID of the new DODAG
|
||||
* @param[out] dodag Pointer to an existing or new DODAG. Otherwise NULL.
|
||||
*
|
||||
* @return true, if DODAG could be created.
|
||||
* @return false, if DODAG could not be created or exists already.
|
||||
*/
|
||||
bool gnrc_rpl_dodag_add(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id,
|
||||
gnrc_rpl_dodag_t **dodag);
|
||||
|
||||
/**
|
||||
* @brief Remove the RPL DODAG @p dodag.
|
||||
*
|
||||
* @param[in] dodag Pointer to the dodag.
|
||||
*
|
||||
* @return true, on success.
|
||||
* @return false, otherwise.
|
||||
*/
|
||||
bool gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag);
|
||||
bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id);
|
||||
|
||||
/**
|
||||
* @brief Remove all parents from the @p dodag.
|
||||
@ -139,17 +115,6 @@ bool gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag);
|
||||
*/
|
||||
void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag);
|
||||
|
||||
/**
|
||||
* @brief Get the RPL DODAG with the id @p dodag_id to the instance @p instance.
|
||||
*
|
||||
* @param[in] instance Pointer to the instance of the RPL DODAG
|
||||
* @param[in] dodag_id The DODAG-ID of the RPL DODAG
|
||||
*
|
||||
* @return Pointer to the existing RPL DODAG, on success.
|
||||
* @return NULL, otherwise.
|
||||
*/
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_dodag_get(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id);
|
||||
|
||||
/**
|
||||
* @brief Add a new parent with the IPv6 address @p addr to the @p dodag.
|
||||
*
|
||||
@ -173,17 +138,6 @@ bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
|
||||
*/
|
||||
bool gnrc_rpl_parent_remove(gnrc_rpl_parent_t *parent);
|
||||
|
||||
/**
|
||||
* @brief Get a parent with the IPv6 addr @p addr of the DODAG @p dodag.
|
||||
*
|
||||
* @param[in] dodag Pointer to the DODAG
|
||||
* @param[in] addr IPv6 address of the parent
|
||||
*
|
||||
* @return Pointer to the existing parent, on success.
|
||||
* @return NULL, otherwise.
|
||||
*/
|
||||
gnrc_rpl_parent_t *gnrc_rpl_parent_get(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Update a @p parent of the @p dodag.
|
||||
*
|
||||
|
||||
@ -165,6 +165,7 @@ typedef struct __attribute__((packed)) {
|
||||
|
||||
typedef struct gnrc_rpl_dodag gnrc_rpl_dodag_t;
|
||||
typedef struct gnrc_rpl_parent gnrc_rpl_parent_t;
|
||||
typedef struct gnrc_rpl_instance gnrc_rpl_instance_t;
|
||||
|
||||
/**
|
||||
* @brief Parent representation
|
||||
@ -195,32 +196,16 @@ typedef struct {
|
||||
void (*process_dio)(void); /**< DIO processing callback (acc. to OF0 spec, chpt 5) */
|
||||
} gnrc_rpl_of_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Instance representation
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t id; /**< id of the instance */
|
||||
uint8_t state; /**< 0 for unused, 1 for used */
|
||||
gnrc_rpl_dodag_t *dodags; /**< pointer to the DODAG list of this instance */
|
||||
uint8_t mop; /**< configured Mode of Operation */
|
||||
gnrc_rpl_of_t *of; /**< configured Objective Function */
|
||||
uint16_t min_hop_rank_inc; /**< minimum hop rank increase */
|
||||
uint16_t max_rank_inc; /**< max increase in the rank */
|
||||
} gnrc_rpl_instance_t;
|
||||
|
||||
/**
|
||||
* @brief DODAG representation
|
||||
*/
|
||||
struct gnrc_rpl_dodag {
|
||||
gnrc_rpl_instance_t *instance; /**< id of the instance */
|
||||
gnrc_rpl_dodag_t *next; /**< pointer to the next dodag */
|
||||
gnrc_rpl_parent_t *parents; /**< pointer to the parents list of this DODAG */
|
||||
ipv6_addr_t dodag_id; /**< id of the DODAG */
|
||||
gnrc_rpl_parent_t *parents; /**< pointer to the parents list of this DODAG */
|
||||
gnrc_rpl_instance_t *instance; /**< pointer to the instance that this dodag is part of */
|
||||
uint8_t prefix_len; /**< length of the prefix for the DODAG id */
|
||||
uint32_t addr_preferred; /**< time in seconds the DODAG id is preferred */
|
||||
uint32_t addr_valid; /**< time in seconds the DODAG id is valid */
|
||||
uint8_t state; /**< 0 for unused, 1 for used */
|
||||
uint8_t dtsn; /**< DAO Trigger Sequence Number */
|
||||
uint8_t prf; /**< preferred flag */
|
||||
uint8_t dio_interval_doubl; /**< trickle Imax parameter */
|
||||
@ -246,6 +231,19 @@ struct gnrc_rpl_dodag {
|
||||
trickle_t trickle; /**< trickle representation */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Instance representation
|
||||
*/
|
||||
struct gnrc_rpl_instance {
|
||||
uint8_t id; /**< id of the instance */
|
||||
uint8_t state; /**< 0 for unused, 1 for used */
|
||||
gnrc_rpl_dodag_t dodag; /**< DODAG of this instance */
|
||||
uint8_t mop; /**< configured Mode of Operation */
|
||||
gnrc_rpl_of_t *of; /**< configured Objective Function */
|
||||
uint16_t min_hop_rank_inc; /**< minimum hop rank increase */
|
||||
uint16_t max_rank_inc; /**< max increase in the rank */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -36,7 +36,6 @@ static mutex_t _inst_id_mutex = MUTEX_INIT;
|
||||
static uint8_t _instance_id;
|
||||
|
||||
gnrc_rpl_instance_t gnrc_rpl_instances[GNRC_RPL_INSTANCES_NUMOF];
|
||||
gnrc_rpl_dodag_t gnrc_rpl_dodags[GNRC_RPL_DODAGS_NUMOF];
|
||||
gnrc_rpl_parent_t gnrc_rpl_parents[GNRC_RPL_PARENTS_NUMOF];
|
||||
|
||||
static void _update_lifetime(void);
|
||||
@ -75,19 +74,23 @@ kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid)
|
||||
return gnrc_rpl_pid;
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id, bool gen_inst_id,
|
||||
bool local_inst_id)
|
||||
gnrc_rpl_instance_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
||||
bool gen_inst_id, bool local_inst_id)
|
||||
{
|
||||
if (gen_inst_id) {
|
||||
instance_id = gnrc_rpl_gen_instance_id(local_inst_id);
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *dodag = gnrc_rpl_root_dodag_init(instance_id, dodag_id, GNRC_RPL_DEFAULT_MOP);
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
gnrc_rpl_instance_t *inst = gnrc_rpl_root_instance_init(instance_id, dodag_id,
|
||||
GNRC_RPL_DEFAULT_MOP);
|
||||
|
||||
if (!dodag) {
|
||||
if (!inst) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
dodag->dtsn = 1;
|
||||
dodag->prf = 0;
|
||||
dodag->dio_interval_doubl = GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
|
||||
@ -106,7 +109,7 @@ gnrc_rpl_dodag_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
||||
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
|
||||
dodag->dio_interval_doubl, dodag->dio_redun);
|
||||
|
||||
return dodag;
|
||||
return inst;
|
||||
}
|
||||
|
||||
static void _receive(gnrc_pktsnip_t *icmpv6)
|
||||
@ -162,6 +165,7 @@ static void *_event_loop(void *args)
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
|
||||
trickle_t *trickle;
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag;
|
||||
/* start event loop */
|
||||
while (1) {
|
||||
@ -189,18 +193,20 @@ static void *_event_loop(void *args)
|
||||
break;
|
||||
case GNRC_RPL_MSG_TYPE_DAO_HANDLE:
|
||||
DEBUG("RPL: GNRC_RPL_MSG_TYPE_DAO_HANDLE received\n");
|
||||
dodag = (gnrc_rpl_dodag_t *) msg.content.ptr;
|
||||
if (dodag && (dodag->state != 0)) {
|
||||
inst = (gnrc_rpl_instance_t *) msg.content.ptr;
|
||||
dodag = &inst->dodag;
|
||||
if (inst && (inst->state != 0)) {
|
||||
_dao_handle_send(dodag);
|
||||
}
|
||||
break;
|
||||
case GNRC_RPL_MSG_TYPE_CLEANUP_HANDLE:
|
||||
DEBUG("RPL: GNRC_RPL_MSG_TYPE_CLEANUP received\n");
|
||||
dodag = (gnrc_rpl_dodag_t *) msg.content.ptr;
|
||||
if (dodag && (dodag->state != 0) && (dodag->parents == NULL)
|
||||
inst = (gnrc_rpl_instance_t *) msg.content.ptr;
|
||||
dodag = &inst->dodag;
|
||||
if (inst && (inst->state != 0) && (dodag->parents == NULL)
|
||||
&& (dodag->my_rank == GNRC_RPL_INFINITE_RANK)) {
|
||||
/* no parents - delete this DODAG */
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
/* no parents - delete this instance and DODAG */
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
}
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_RCV:
|
||||
@ -238,7 +244,7 @@ void _update_lifetime(void)
|
||||
}
|
||||
else if ((int64_t)(parent->lifetime - now) <=
|
||||
(int64_t) (GNRC_RPL_LIFETIME_UPDATE_STEP * SEC_IN_USEC * 2)) {
|
||||
gnrc_rpl_send_DIS(parent->dodag, &parent->addr);
|
||||
gnrc_rpl_send_DIS(parent->dodag->instance, &parent->addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,7 +271,7 @@ void _dao_handle_send(gnrc_rpl_dodag_t *dodag)
|
||||
{
|
||||
if ((dodag->dao_ack_received == false) && (dodag->dao_counter < GNRC_RPL_DAO_SEND_RETRIES)) {
|
||||
dodag->dao_counter++;
|
||||
gnrc_rpl_send_DAO(dodag, NULL, dodag->default_lifetime);
|
||||
gnrc_rpl_send_DAO(dodag->instance, NULL, dodag->default_lifetime);
|
||||
dodag->dao_time = GNRC_RPL_DEFAULT_WAIT_FOR_DAO_ACK * SEC_IN_USEC;
|
||||
xtimer_set_msg64(&dodag->dao_timer, dodag->dao_time, &dodag->dao_msg, gnrc_rpl_pid);
|
||||
}
|
||||
|
||||
@ -89,13 +89,14 @@ void gnrc_rpl_send(gnrc_pktsnip_t *pkt, ipv6_addr_t *src, ipv6_addr_t *dst, ipv6
|
||||
|
||||
}
|
||||
|
||||
void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
|
||||
{
|
||||
if (dodag == NULL) {
|
||||
if (inst == NULL) {
|
||||
DEBUG("RPL: Error - trying to send DIO without being part of a dodag.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
||||
gnrc_pktsnip_t *pkt;
|
||||
icmpv6_hdr_t *icmp;
|
||||
gnrc_rpl_dio_t *dio;
|
||||
@ -118,13 +119,13 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
icmp = (icmpv6_hdr_t *)pkt->data;
|
||||
dio = (gnrc_rpl_dio_t *)(icmp + 1);
|
||||
pos = (uint8_t *) dio;
|
||||
dio->instance_id = dodag->instance->id;
|
||||
dio->instance_id = inst->id;
|
||||
dio->version_number = dodag->version;
|
||||
/* a leaf node announces an INFINITE_RANK */
|
||||
dio->rank = ((dodag->node_status == GNRC_RPL_LEAF_NODE) ?
|
||||
byteorder_htons(GNRC_RPL_INFINITE_RANK) : byteorder_htons(dodag->my_rank));
|
||||
dio->g_mop_prf = (dodag->grounded << GNRC_RPL_GROUNDED_SHIFT) |
|
||||
(dodag->instance->mop << GNRC_RPL_MOP_SHIFT) | dodag->prf;
|
||||
(inst->mop << GNRC_RPL_MOP_SHIFT) | dodag->prf;
|
||||
dio->dtsn = dodag->dtsn;
|
||||
dio->flags = 0;
|
||||
dio->reserved = 0;
|
||||
@ -141,9 +142,9 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
dodag_conf->dio_int_doubl = dodag->dio_interval_doubl;
|
||||
dodag_conf->dio_int_min = dodag->dio_min;
|
||||
dodag_conf->dio_redun = dodag->dio_redun;
|
||||
dodag_conf->max_rank_inc = byteorder_htons(dodag->instance->max_rank_inc);
|
||||
dodag_conf->min_hop_rank_inc = byteorder_htons(dodag->instance->min_hop_rank_inc);
|
||||
dodag_conf->ocp = byteorder_htons(dodag->instance->of->ocp);
|
||||
dodag_conf->max_rank_inc = byteorder_htons(inst->max_rank_inc);
|
||||
dodag_conf->min_hop_rank_inc = byteorder_htons(inst->min_hop_rank_inc);
|
||||
dodag_conf->ocp = byteorder_htons(inst->of->ocp);
|
||||
dodag_conf->reserved = 0;
|
||||
dodag_conf->default_lifetime = dodag->default_lifetime;
|
||||
dodag_conf->lifetime_unit = byteorder_htons(dodag->lifetime_unit);
|
||||
@ -171,7 +172,7 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);
|
||||
}
|
||||
|
||||
void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
void gnrc_rpl_send_DIS(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt;
|
||||
icmpv6_hdr_t *icmp;
|
||||
@ -199,7 +200,7 @@ void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
/* TODO add padding may be removed if packet size grows */
|
||||
memcpy((dis + 1), padding, sizeof(padding));
|
||||
|
||||
gnrc_rpl_send(pkt, NULL, destination, (dodag ? &dodag->dodag_id : NULL));
|
||||
gnrc_rpl_send(pkt, NULL, destination, (inst? &(inst->dodag.dodag_id) : NULL));
|
||||
}
|
||||
|
||||
static bool _gnrc_rpl_check_DIS_validity(gnrc_rpl_dis_t *dis, uint16_t len)
|
||||
@ -226,26 +227,26 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, ipv6_addr_t *src, ipv6_addr_t *dst,
|
||||
}
|
||||
|
||||
if (ipv6_addr_is_multicast(dst)) {
|
||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||
if ((gnrc_rpl_dodags[i].state != 0)
|
||||
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
||||
if ((gnrc_rpl_instances[i].state != 0)
|
||||
/* a leaf node should only react to unicast DIS */
|
||||
&& (gnrc_rpl_dodags[i].node_status != GNRC_RPL_LEAF_NODE)) {
|
||||
trickle_reset_timer(&gnrc_rpl_dodags[i].trickle);
|
||||
&& (gnrc_rpl_instances[i].dodag.node_status != GNRC_RPL_LEAF_NODE)) {
|
||||
trickle_reset_timer(&(gnrc_rpl_instances[i].dodag.trickle));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||
if (gnrc_rpl_dodags[i].state != 0) {
|
||||
gnrc_rpl_dodags[i].dodag_conf_requested = true;
|
||||
gnrc_rpl_dodags[i].prefix_info_requested = true;
|
||||
gnrc_rpl_send_DIO(&gnrc_rpl_dodags[i], src);
|
||||
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
||||
if (gnrc_rpl_instances[i].state != 0) {
|
||||
gnrc_rpl_instances[i].dodag.dodag_conf_requested = true;
|
||||
gnrc_rpl_instances[i].dodag.prefix_info_requested = true;
|
||||
gnrc_rpl_send_DIO(&gnrc_rpl_instances[i], src);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_dodag_t *dodag,
|
||||
static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_instance_t *inst,
|
||||
gnrc_rpl_opt_t *opt, uint16_t len)
|
||||
{
|
||||
uint16_t expected_len = 0;
|
||||
@ -303,7 +304,7 @@ static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_dodag_t *dod
|
||||
}
|
||||
|
||||
uint8_t parent_addr = 0;
|
||||
if (dodag->instance->mop == GNRC_RPL_MOP_NON_STORING_MODE) {
|
||||
if (inst->mop == GNRC_RPL_MOP_NON_STORING_MODE) {
|
||||
parent_addr = sizeof(ipv6_addr_t);
|
||||
}
|
||||
|
||||
@ -332,16 +333,17 @@ static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_dodag_t *dod
|
||||
}
|
||||
|
||||
/** @todo allow target prefixes in target options to be of variable length */
|
||||
bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt, uint16_t len,
|
||||
bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt, uint16_t len,
|
||||
ipv6_addr_t *src, uint32_t *included_opts)
|
||||
{
|
||||
uint16_t l = 0;
|
||||
gnrc_rpl_opt_target_t *first_target = NULL;
|
||||
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
||||
eui64_t iid;
|
||||
kernel_pid_t if_id = KERNEL_PID_UNDEF;
|
||||
*included_opts = 0;
|
||||
|
||||
if (!_gnrc_rpl_check_options_validity(msg_type, dodag, opt, len)) {
|
||||
if (!_gnrc_rpl_check_options_validity(msg_type, inst, opt, len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -366,17 +368,17 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
||||
gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
|
||||
gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
|
||||
if (of != NULL) {
|
||||
dodag->instance->of = of;
|
||||
inst->of = of;
|
||||
}
|
||||
else {
|
||||
DEBUG("RPL: Unsupported OCP 0x%02x\n", byteorder_ntohs(dc->ocp));
|
||||
dodag->instance->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
|
||||
inst->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
|
||||
}
|
||||
dodag->dio_interval_doubl = dc->dio_int_doubl;
|
||||
dodag->dio_min = dc->dio_int_min;
|
||||
dodag->dio_redun = dc->dio_redun;
|
||||
dodag->instance->max_rank_inc = byteorder_ntohs(dc->max_rank_inc);
|
||||
dodag->instance->min_hop_rank_inc = byteorder_ntohs(dc->min_hop_rank_inc);
|
||||
inst->max_rank_inc = byteorder_ntohs(dc->max_rank_inc);
|
||||
inst->min_hop_rank_inc = byteorder_ntohs(dc->min_hop_rank_inc);
|
||||
dodag->default_lifetime = dc->default_lifetime;
|
||||
dodag->lifetime_unit = byteorder_ntohs(dc->lifetime_unit);
|
||||
dodag->trickle.Imin = (1 << dodag->dio_min);
|
||||
@ -442,7 +444,7 @@ a preceding RPL TARGET DAO option\n");
|
||||
(transit->path_lifetime *
|
||||
dodag->lifetime_unit * SEC_IN_MS));
|
||||
first_target = (gnrc_rpl_opt_target_t *) (((uint8_t *) (first_target)) +
|
||||
sizeof(gnrc_rpl_opt_t) + first_target->length);
|
||||
sizeof(gnrc_rpl_opt_t) + first_target->length);
|
||||
}
|
||||
while (first_target->type == GNRC_RPL_OPT_TARGET);
|
||||
|
||||
@ -481,45 +483,48 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
len -= (sizeof(gnrc_rpl_dio_t) + sizeof(icmpv6_hdr_t));
|
||||
|
||||
if (gnrc_rpl_instance_add(dio->instance_id, &inst)) {
|
||||
/* new instance and DODAG */
|
||||
|
||||
if (byteorder_ntohs(dio->rank) == GNRC_RPL_INFINITE_RANK) {
|
||||
DEBUG("RPL: ignore INFINITE_RANK DIO when we are not yet part of this DODAG\n");
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
inst->mop = (dio->g_mop_prf >> GNRC_RPL_MOP_SHIFT) & GNRC_RPL_SHIFTED_MOP_MASK;
|
||||
inst->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
|
||||
}
|
||||
else if (inst == NULL) {
|
||||
DEBUG("RPL: Could not allocate a new instance.\n");
|
||||
return;
|
||||
}
|
||||
gnrc_rpl_dodag_init(inst, &dio->dodag_id);
|
||||
|
||||
if ((byteorder_ntohs(dio->rank) == GNRC_RPL_INFINITE_RANK) &&
|
||||
(gnrc_rpl_dodag_get(inst, &dio->dodag_id) == NULL)) {
|
||||
DEBUG("RPL: ignore INFINITE_RANK DIO when we are not part of this DODAG\n");
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
return;
|
||||
}
|
||||
dodag = &inst->dodag;
|
||||
|
||||
DEBUG("RPL: Joined DODAG (%s).\n",
|
||||
ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str)));
|
||||
|
||||
if (gnrc_rpl_dodag_add(inst, &dio->dodag_id, &dodag)) {
|
||||
gnrc_rpl_parent_t *parent = NULL;
|
||||
|
||||
if (!gnrc_rpl_parent_add_by_addr(dodag, src, &parent) && (parent == NULL)) {
|
||||
DEBUG("RPL: Could not allocate new parent.\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
dodag->version = dio->version_number;
|
||||
dodag->grounded = dio->g_mop_prf >> GNRC_RPL_GROUNDED_SHIFT;
|
||||
dodag->prf = dio->g_mop_prf & GNRC_RPL_PRF_MASK;
|
||||
|
||||
parent->rank = byteorder_ntohs(dio->rank);
|
||||
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag, (gnrc_rpl_opt_t *)(dio + 1), len, NULL,
|
||||
&included_opts)) {
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, inst, (gnrc_rpl_opt_t *)(dio + 1), len,
|
||||
NULL, &included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(included_opts & (((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF))) {
|
||||
DEBUG("RPL: DIO without DODAG_CONF option - remove DODAG and request new DIO\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
gnrc_rpl_send_DIS(NULL, src);
|
||||
return;
|
||||
}
|
||||
@ -530,20 +535,26 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
dodag->dio_interval_doubl, dodag->dio_redun);
|
||||
|
||||
gnrc_rpl_parent_update(dodag, parent);
|
||||
DEBUG("RPL: Joined DODAG (%s).\n",
|
||||
ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str)));
|
||||
return;
|
||||
}
|
||||
else if (dodag == NULL) {
|
||||
DEBUG("RPL: Could not allocate a new DODAG.\n");
|
||||
if (inst->dodags == NULL) {
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
}
|
||||
else if (inst == NULL) {
|
||||
DEBUG("RPL: Could not allocate a new instance.\n");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* instance exists already */
|
||||
/* ignore dodags with other dodag_id's for now */
|
||||
/* TODO: choose DODAG with better rank */
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
if (memcmp(&dodag->dodag_id, &dio->dodag_id, sizeof(ipv6_addr_t)) != 0) {
|
||||
DEBUG("RPL: DIO received from another DODAG, but same instance - ignore\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (dodag->instance->mop !=
|
||||
((dio->g_mop_prf >> GNRC_RPL_MOP_SHIFT) & GNRC_RPL_SHIFTED_MOP_MASK)) {
|
||||
if (inst->mop != ((dio->g_mop_prf >> GNRC_RPL_MOP_SHIFT) & GNRC_RPL_SHIFTED_MOP_MASK)) {
|
||||
DEBUG("RPL: invalid MOP for this instance.\n");
|
||||
return;
|
||||
}
|
||||
@ -577,9 +588,6 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
|
||||
if (!gnrc_rpl_parent_add_by_addr(dodag, src, &parent) && (parent == NULL)) {
|
||||
DEBUG("RPL: Could not allocate new parent.\n");
|
||||
if (dodag->parents == NULL) {
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* cppcheck-suppress nullPointer */
|
||||
@ -612,10 +620,10 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
dodag->grounded = dio->g_mop_prf >> GNRC_RPL_GROUNDED_SHIFT;
|
||||
dodag->prf = dio->g_mop_prf & GNRC_RPL_PRF_MASK;
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag, (gnrc_rpl_opt_t *)(dio + 1), len, NULL,
|
||||
&included_opts)) {
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, inst, (gnrc_rpl_opt_t *)(dio + 1), len,
|
||||
NULL, &included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -661,16 +669,19 @@ gnrc_pktsnip_t *_dao_transit_build(gnrc_pktsnip_t *pkt, uint8_t lifetime)
|
||||
return opt_snip;
|
||||
}
|
||||
|
||||
void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_t lifetime)
|
||||
void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint8_t lifetime)
|
||||
{
|
||||
gnrc_rpl_dodag_t *dodag;
|
||||
size_t dst_size = GNRC_IPV6_FIB_TABLE_SIZE;
|
||||
fib_destination_set_entry_t fib_dest_set[GNRC_IPV6_FIB_TABLE_SIZE];
|
||||
|
||||
if (dodag == NULL) {
|
||||
if (inst == NULL) {
|
||||
DEBUG("RPL: Error - trying to send DAO without being part of a dodag.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
if (dodag->node_status == GNRC_RPL_ROOT_NODE) {
|
||||
return;
|
||||
}
|
||||
@ -729,7 +740,7 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_
|
||||
return;
|
||||
}
|
||||
|
||||
bool local_instance = (dodag->instance->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false;
|
||||
bool local_instance = (inst->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false;
|
||||
|
||||
if (local_instance) {
|
||||
if ((tmp = gnrc_pktbuf_add(pkt, &dodag->dodag_id, sizeof(ipv6_addr_t),
|
||||
@ -748,7 +759,7 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_
|
||||
}
|
||||
pkt = tmp;
|
||||
dao = pkt->data;
|
||||
dao->instance_id = dodag->instance->id;
|
||||
dao->instance_id = inst->id;
|
||||
if (local_instance) {
|
||||
/* set the D flag to indicate that a DODAG id is present */
|
||||
dao->k_d_flags = GNRC_RPL_DAO_D_BIT;
|
||||
@ -774,18 +785,22 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_
|
||||
GNRC_RPL_COUNTER_INCREMENT(dodag->dao_seq);
|
||||
}
|
||||
|
||||
void gnrc_rpl_send_DAO_ACK(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_t seq)
|
||||
void gnrc_rpl_send_DAO_ACK(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint8_t seq)
|
||||
{
|
||||
if (dodag == NULL) {
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
|
||||
if (inst == NULL) {
|
||||
DEBUG("RPL: Error - trying to send DAO-ACK without being part of a dodag.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
gnrc_pktsnip_t *pkt;
|
||||
icmpv6_hdr_t *icmp;
|
||||
gnrc_rpl_dao_ack_t *dao_ack;
|
||||
int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dao_ack_t);
|
||||
bool local_instance = (dodag->instance->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false;
|
||||
bool local_instance = (inst->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false;
|
||||
|
||||
if (local_instance) {
|
||||
size += sizeof(ipv6_addr_t);
|
||||
@ -799,7 +814,7 @@ void gnrc_rpl_send_DAO_ACK(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, ui
|
||||
icmp = (icmpv6_hdr_t *)pkt->data;
|
||||
dao_ack = (gnrc_rpl_dao_ack_t *)(icmp + 1);
|
||||
|
||||
dao_ack->instance_id = dodag->instance->id;
|
||||
dao_ack->instance_id = inst->id;
|
||||
if (local_instance) {
|
||||
/* set the D flag to indicate that a DODAG id is present */
|
||||
dao_ack->d_reserved = GNRC_RPL_DAO_ACK_D_BIT;
|
||||
@ -848,11 +863,13 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
len -= (sizeof(gnrc_rpl_dao_t) + sizeof(icmpv6_hdr_t));
|
||||
|
||||
/* check if the D flag is set before accessing the DODAG id */
|
||||
if ((dao->k_d_flags & GNRC_RPL_DAO_D_BIT)) {
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, (ipv6_addr_t *)(dao + 1))) == NULL) {
|
||||
if (memcmp(&dodag->dodag_id, (ipv6_addr_t *)(dao + 1), sizeof(ipv6_addr_t)) != 0) {
|
||||
DEBUG("RPL: DAO with unknown DODAG id (%s)\n", ipv6_addr_to_str(addr_str,
|
||||
(ipv6_addr_t *)(dao + 1), sizeof(addr_str)));
|
||||
return;
|
||||
@ -860,12 +877,6 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
||||
opts = (gnrc_rpl_opt_t *)(((uint8_t *) opts) + sizeof(ipv6_addr_t));
|
||||
len -= sizeof(ipv6_addr_t);
|
||||
}
|
||||
else {
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, NULL)) == NULL) {
|
||||
DEBUG("RPL: DAO for instance (%d) without DODAGs\n", dao->instance_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* a leaf node should not parse DAOs */
|
||||
if (dodag->node_status == GNRC_RPL_LEAF_NODE) {
|
||||
@ -873,14 +884,14 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
||||
}
|
||||
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, dodag, opts, len, src, &included_opts)) {
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, inst, opts, len, src, &included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DAO option parsing - ignore DAO\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* send a DAO-ACK if K flag is set */
|
||||
if (dao->k_d_flags & GNRC_RPL_DAO_K_BIT) {
|
||||
gnrc_rpl_send_DAO_ACK(dodag, src, dao->dao_sequence);
|
||||
gnrc_rpl_send_DAO_ACK(inst, src, dao->dao_sequence);
|
||||
}
|
||||
|
||||
gnrc_rpl_delay_dao(dodag);
|
||||
@ -917,19 +928,16 @@ void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, uint16_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
|
||||
/* check if the D flag is set before accessing the DODAG id */
|
||||
if ((dao_ack->d_reserved & GNRC_RPL_DAO_ACK_D_BIT)) {
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, (ipv6_addr_t *)(dao_ack + 1))) == NULL) {
|
||||
if (memcmp(&dodag->dodag_id, (ipv6_addr_t *)(dao_ack + 1), sizeof(ipv6_addr_t)) != 0) {
|
||||
DEBUG("RPL: DAO-ACK with unknown DODAG id (%s)\n", ipv6_addr_to_str(addr_str,
|
||||
(ipv6_addr_t *)(dao_ack + 1), sizeof(addr_str)));
|
||||
(ipv6_addr_t *)(dao_ack + 1), sizeof(addr_str)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* D flag not set - global instance id */
|
||||
else if ((dodag = gnrc_rpl_dodag_get(inst, NULL)) == NULL) {
|
||||
DEBUG("RPL: DAO-ACK for instance (%d) without DODAGs\n", dao_ack->instance_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dao_ack->status != 0) && (dao_ack->dao_sequence != dodag->dao_seq)) {
|
||||
DEBUG("RPL: DAO-ACK sequence (%d) does not match expected sequence (%d)\n",
|
||||
|
||||
@ -34,11 +34,11 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *dodag);
|
||||
static void _rpl_trickle_send_dio(void *args);
|
||||
static int _compare_parents(gnrc_rpl_parent_t *p1, gnrc_rpl_parent_t *p2);
|
||||
|
||||
static void _rpl_trickle_send_dio(void *args)
|
||||
{
|
||||
gnrc_rpl_dodag_t *dodag = (gnrc_rpl_dodag_t *) args;
|
||||
gnrc_rpl_instance_t *inst = (gnrc_rpl_instance_t *) args;
|
||||
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||
|
||||
/* a leaf node does not send DIOs periodically */
|
||||
@ -47,9 +47,9 @@ static void _rpl_trickle_send_dio(void *args)
|
||||
return;
|
||||
}
|
||||
|
||||
gnrc_rpl_send_DIO(dodag, &all_RPL_nodes);
|
||||
DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", dodag->instance->id,
|
||||
ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));
|
||||
gnrc_rpl_send_DIO(inst, &all_RPL_nodes);
|
||||
DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", inst->id,
|
||||
ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));
|
||||
}
|
||||
|
||||
bool gnrc_rpl_instance_add(uint8_t instance_id, gnrc_rpl_instance_t **inst)
|
||||
@ -75,7 +75,7 @@ bool gnrc_rpl_instance_add(uint8_t instance_id, gnrc_rpl_instance_t **inst)
|
||||
(*inst)->state = 1;
|
||||
(*inst)->max_rank_inc = GNRC_RPL_DEFAULT_MAX_RANK_INCREASE;
|
||||
(*inst)->min_hop_rank_inc = GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE;
|
||||
(*inst)->dodags = NULL;
|
||||
(*inst)->dodag.parents = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -89,12 +89,7 @@ bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
|
||||
{
|
||||
for(uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
||||
if (gnrc_rpl_instances[i].id == instance_id) {
|
||||
gnrc_rpl_dodag_t *elt, *tmp;
|
||||
LL_FOREACH_SAFE(gnrc_rpl_instances[i].dodags, elt, tmp) {
|
||||
gnrc_rpl_dodag_remove(elt);
|
||||
}
|
||||
memset(&gnrc_rpl_instances[i], 0, sizeof(gnrc_rpl_instance_t));
|
||||
return true;
|
||||
return gnrc_rpl_instance_remove(&gnrc_rpl_instances[i]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -102,10 +97,11 @@ bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
|
||||
|
||||
bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
|
||||
{
|
||||
gnrc_rpl_dodag_t *elt, *tmp;
|
||||
LL_FOREACH_SAFE(inst->dodags, elt, tmp) {
|
||||
gnrc_rpl_dodag_remove(elt);
|
||||
}
|
||||
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
||||
gnrc_rpl_dodag_remove_all_parents(dodag);
|
||||
trickle_stop(&dodag->trickle);
|
||||
xtimer_remove(&dodag->dao_timer);
|
||||
xtimer_remove(&dodag->cleanup_timer);
|
||||
memset(inst, 0, sizeof(gnrc_rpl_instance_t));
|
||||
return true;
|
||||
}
|
||||
@ -113,87 +109,48 @@ bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
|
||||
gnrc_rpl_instance_t *gnrc_rpl_instance_get(uint8_t instance_id)
|
||||
{
|
||||
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
||||
if (gnrc_rpl_instances[i].id == instance_id) {
|
||||
if ((gnrc_rpl_instances[i].state != 0) && (gnrc_rpl_instances[i].id == instance_id)) {
|
||||
return &gnrc_rpl_instances[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gnrc_rpl_dodag_add(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id, gnrc_rpl_dodag_t **dodag)
|
||||
bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id)
|
||||
{
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
|
||||
if ((instance == NULL) || instance->state == 0) {
|
||||
DEBUG("Instance is NULL or unused\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*dodag = NULL;
|
||||
bool first = true;
|
||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||
/* save position to the first unused instance */
|
||||
if ((gnrc_rpl_dodags[i].state == 0) && first) {
|
||||
*dodag = &gnrc_rpl_dodags[i];
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
else if ((gnrc_rpl_dodags[i].state != 0) &&
|
||||
(gnrc_rpl_dodags[i].instance->id == instance->id) &&
|
||||
ipv6_addr_equal(&gnrc_rpl_dodags[i].dodag_id, dodag_id)) {
|
||||
DEBUG("DODAG with id: %s does exist\n", ipv6_addr_to_str(addr_str, dodag_id,
|
||||
sizeof(addr_str)));
|
||||
*dodag = &gnrc_rpl_dodags[i];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dodag = &instance->dodag;
|
||||
|
||||
if (*dodag != NULL) {
|
||||
(*dodag)->instance = instance;
|
||||
LL_APPEND(instance->dodags, *dodag);
|
||||
(*dodag)->state = 1;
|
||||
(*dodag)->dodag_id = *dodag_id;
|
||||
(*dodag)->prefix_len = GNRC_RPL_DEFAULT_PREFIX_LEN;
|
||||
(*dodag)->addr_preferred = GNRC_RPL_DEFAULT_PREFIX_LIFETIME;
|
||||
(*dodag)->addr_valid = GNRC_RPL_DEFAULT_PREFIX_LIFETIME;
|
||||
(*dodag)->my_rank = GNRC_RPL_INFINITE_RANK;
|
||||
(*dodag)->trickle.callback.func = &_rpl_trickle_send_dio;
|
||||
(*dodag)->trickle.callback.args = *dodag;
|
||||
(*dodag)->dio_interval_doubl = GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
|
||||
(*dodag)->dio_min = GNRC_RPL_DEFAULT_DIO_INTERVAL_MIN;
|
||||
(*dodag)->dio_redun = GNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT;
|
||||
(*dodag)->default_lifetime = GNRC_RPL_DEFAULT_LIFETIME;
|
||||
(*dodag)->lifetime_unit = GNRC_RPL_LIFETIME_UNIT;
|
||||
(*dodag)->node_status = GNRC_RPL_NORMAL_NODE;
|
||||
(*dodag)->dao_seq = GNRC_RPL_COUNTER_INIT;
|
||||
(*dodag)->dtsn = 0;
|
||||
(*dodag)->dao_ack_received = false;
|
||||
(*dodag)->dao_counter = 0;
|
||||
(*dodag)->parents = NULL;
|
||||
(*dodag)->dao_msg.type = GNRC_RPL_MSG_TYPE_DAO_HANDLE;
|
||||
(*dodag)->dao_msg.content.ptr = (char *) (*dodag);
|
||||
(*dodag)->cleanup_time = GNRC_RPL_CLEANUP_TIME * SEC_IN_USEC;
|
||||
(*dodag)->cleanup_msg.type = GNRC_RPL_MSG_TYPE_CLEANUP_HANDLE;
|
||||
(*dodag)->cleanup_msg.content.ptr = (char *) (*dodag);
|
||||
return true;
|
||||
}
|
||||
dodag->dodag_id = *dodag_id;
|
||||
dodag->prefix_len = GNRC_RPL_DEFAULT_PREFIX_LEN;
|
||||
dodag->addr_preferred = GNRC_RPL_DEFAULT_PREFIX_LIFETIME;
|
||||
dodag->addr_valid = GNRC_RPL_DEFAULT_PREFIX_LIFETIME;
|
||||
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
||||
dodag->trickle.callback.func = &_rpl_trickle_send_dio;
|
||||
dodag->trickle.callback.args = instance;
|
||||
dodag->dio_interval_doubl = GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
|
||||
dodag->dio_min = GNRC_RPL_DEFAULT_DIO_INTERVAL_MIN;
|
||||
dodag->dio_redun = GNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT;
|
||||
dodag->default_lifetime = GNRC_RPL_DEFAULT_LIFETIME;
|
||||
dodag->lifetime_unit = GNRC_RPL_LIFETIME_UNIT;
|
||||
dodag->node_status = GNRC_RPL_NORMAL_NODE;
|
||||
dodag->dao_seq = GNRC_RPL_COUNTER_INIT;
|
||||
dodag->dtsn = 0;
|
||||
dodag->dao_ack_received = false;
|
||||
dodag->dao_counter = 0;
|
||||
dodag->dao_msg.type = GNRC_RPL_MSG_TYPE_DAO_HANDLE;
|
||||
dodag->dao_msg.content.ptr = (char *) instance;
|
||||
dodag->cleanup_time = GNRC_RPL_CLEANUP_TIME * SEC_IN_USEC;
|
||||
dodag->cleanup_msg.type = GNRC_RPL_MSG_TYPE_CLEANUP_HANDLE;
|
||||
dodag->cleanup_msg.content.ptr = (char *) instance;
|
||||
dodag->instance = instance;
|
||||
|
||||
/* no space available to allocate a new dodag */
|
||||
DEBUG("Could not allocate a new RPL DODAG\n");
|
||||
*dodag = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag)
|
||||
{
|
||||
gnrc_rpl_dodag_remove_all_parents(dodag);
|
||||
gnrc_rpl_instance_t *inst = dodag->instance;
|
||||
LL_DELETE(inst->dodags, dodag);
|
||||
trickle_stop(&dodag->trickle);
|
||||
xtimer_remove(&dodag->dao_timer);
|
||||
xtimer_remove(&dodag->cleanup_timer);
|
||||
memset(dodag, 0, sizeof(gnrc_rpl_dodag_t));
|
||||
if (inst->dodags == NULL) {
|
||||
gnrc_rpl_instance_remove(inst);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -206,55 +163,22 @@ void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag)
|
||||
xtimer_set_msg(&dodag->cleanup_timer, dodag->cleanup_time, &dodag->cleanup_msg, gnrc_rpl_pid);
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_dodag_get(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id)
|
||||
bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
|
||||
gnrc_rpl_parent_t **parent)
|
||||
{
|
||||
if ((instance == NULL) || (instance->state == 0)) {
|
||||
DEBUG("Instance is NULL or unused\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if global instance id */
|
||||
if ((dodag_id == NULL) && ((instance->id & GNRC_RPL_INSTANCE_ID_MSB) == 0)) {
|
||||
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
|
||||
if ((instance->dodags != NULL) && (instance->dodags->next != NULL)) {
|
||||
DEBUG("RPL: More than one DODAG available for the global instance (%d)", instance->id);
|
||||
}
|
||||
#endif
|
||||
return instance->dodags;
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
LL_FOREACH(instance->dodags, dodag) {
|
||||
if (ipv6_addr_equal(&dodag->dodag_id, dodag_id)) {
|
||||
return dodag;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr, gnrc_rpl_parent_t **parent)
|
||||
{
|
||||
if ((dodag == NULL) || (dodag->state == 0)) {
|
||||
DEBUG("DODAG is NULL or unused\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*parent = NULL;
|
||||
bool first = true;
|
||||
for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) {
|
||||
/* save position to the first unused instance */
|
||||
/* save position to the first unused parent */
|
||||
if ((gnrc_rpl_parents[i].state == 0) && first) {
|
||||
*parent = &gnrc_rpl_parents[i];
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
/* return false if parent exists */
|
||||
else if ((gnrc_rpl_parents[i].state != 0) &&
|
||||
(gnrc_rpl_parents[i].dodag->instance->id == dodag->instance->id) &&
|
||||
ipv6_addr_equal(&gnrc_rpl_parents[i].dodag->dodag_id, &dodag->dodag_id) &&
|
||||
ipv6_addr_equal(&gnrc_rpl_parents[i].addr, addr)) {
|
||||
DEBUG("parent with addr: %s does exist\n", ipv6_addr_to_str(addr_str, addr,
|
||||
sizeof(addr_str)));
|
||||
else if ((gnrc_rpl_parents[i].state != 0) && (gnrc_rpl_parents[i].dodag == dodag) &&
|
||||
ipv6_addr_equal(&gnrc_rpl_parents[i].addr, addr)) {
|
||||
DEBUG("parent (%s) exists\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
|
||||
*parent = &gnrc_rpl_parents[i];
|
||||
return false;
|
||||
}
|
||||
@ -265,24 +189,6 @@ bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr, gnr
|
||||
LL_APPEND(dodag->parents, *parent);
|
||||
(*parent)->state = 1;
|
||||
(*parent)->addr = *addr;
|
||||
if ((*parent) == (*parent)->dodag->parents) {
|
||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||
ipv6_addr_t def = IPV6_ADDR_UNSPECIFIED;
|
||||
kernel_pid_t if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
|
||||
if (if_id == KERNEL_PID_UNDEF) {
|
||||
DEBUG("RPL: no interface found for the parent addres\n");
|
||||
return false;
|
||||
}
|
||||
if (fib_add_entry(&gnrc_ipv6_fib_table, if_id, def.u8,
|
||||
sizeof(ipv6_addr_t), 0x0,
|
||||
dodag->parents->addr.u8, sizeof(ipv6_addr_t),
|
||||
FIB_FLAG_RPL_ROUTE, (dodag->default_lifetime *
|
||||
dodag->lifetime_unit) * SEC_IN_MS) != 0) {
|
||||
DEBUG("RPL: error adding parent to FIB\n");
|
||||
gnrc_rpl_parent_remove(*parent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -292,30 +198,13 @@ bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr, gnr
|
||||
return false;
|
||||
}
|
||||
|
||||
gnrc_rpl_parent_t *gnrc_rpl_parent_get(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr)
|
||||
{
|
||||
if ((dodag == NULL) || (dodag->state == 0)) {
|
||||
DEBUG("DODAG is NULL or unused\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gnrc_rpl_parent_t *parent = NULL;
|
||||
LL_FOREACH(dodag->parents, parent) {
|
||||
if (ipv6_addr_equal(&parent->addr, addr)) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gnrc_rpl_parent_remove(gnrc_rpl_parent_t *parent)
|
||||
{
|
||||
if (parent == parent->dodag->parents) {
|
||||
ipv6_addr_t def = { .u64 = {{0}, {0}} };
|
||||
ipv6_addr_t def = IPV6_ADDR_UNSPECIFIED;
|
||||
fib_remove_entry(&gnrc_ipv6_fib_table, def.u8, sizeof(ipv6_addr_t));
|
||||
}
|
||||
gnrc_rpl_dodag_t *dodag = parent->dodag;
|
||||
LL_DELETE(dodag->parents, parent);
|
||||
LL_DELETE(parent->dodag->parents, parent);
|
||||
memset(parent, 0, sizeof(gnrc_rpl_parent_t));
|
||||
return true;
|
||||
}
|
||||
@ -333,12 +222,11 @@ void gnrc_rpl_local_repair(gnrc_rpl_dodag_t *dodag)
|
||||
}
|
||||
|
||||
if (dodag->my_rank != GNRC_RPL_INFINITE_RANK) {
|
||||
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
||||
trickle_reset_timer(&dodag->trickle);
|
||||
xtimer_set_msg(&dodag->cleanup_timer, dodag->cleanup_time, &dodag->cleanup_msg,
|
||||
gnrc_rpl_pid);
|
||||
}
|
||||
|
||||
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
||||
}
|
||||
|
||||
void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
|
||||
@ -354,11 +242,9 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
|
||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||
kernel_pid_t if_id;
|
||||
if ((if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes)) != KERNEL_PID_UNDEF) {
|
||||
fib_add_entry(&gnrc_ipv6_fib_table, if_id, def.u8,
|
||||
sizeof(ipv6_addr_t), 0x0,
|
||||
dodag->parents->addr.u8, sizeof(ipv6_addr_t),
|
||||
FIB_FLAG_RPL_ROUTE, (dodag->default_lifetime *
|
||||
dodag->lifetime_unit) * SEC_IN_MS);
|
||||
fib_add_entry(&gnrc_ipv6_fib_table, if_id, def.u8, sizeof(ipv6_addr_t), 0x0,
|
||||
parent->addr.u8, sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
|
||||
(dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -372,11 +258,6 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
|
||||
}
|
||||
}
|
||||
|
||||
static int _compare_parents(gnrc_rpl_parent_t *p1, gnrc_rpl_parent_t *p2)
|
||||
{
|
||||
return p1->dodag->instance->of->which_parent(p1, p2) == p1 ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the parent with the lowest rank and update the DODAG's preferred parent
|
||||
*
|
||||
@ -389,48 +270,63 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
|
||||
{
|
||||
ipv6_addr_t def = IPV6_ADDR_UNSPECIFIED;
|
||||
gnrc_rpl_parent_t *old_best = dodag->parents;
|
||||
gnrc_rpl_parent_t *new_best = old_best;
|
||||
uint16_t old_rank = dodag->my_rank;
|
||||
gnrc_rpl_parent_t *elt = NULL, *tmp = NULL;
|
||||
|
||||
LL_SORT(dodag->parents, _compare_parents);
|
||||
|
||||
if ((dodag->parents == NULL) || (dodag->parents->rank >= dodag->my_rank)) {
|
||||
if (dodag->parents == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dodag->my_rank = dodag->instance->of->calc_rank(dodag->parents, 0);
|
||||
gnrc_rpl_parent_t *elt, *tmp;
|
||||
LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
|
||||
if (dodag->parents->rank < elt->rank) {
|
||||
gnrc_rpl_parent_remove(elt);
|
||||
}
|
||||
new_best = dodag->instance->of->which_parent(new_best, elt);
|
||||
}
|
||||
|
||||
if (old_best != dodag->parents) {
|
||||
if (new_best->rank == GNRC_RPL_INFINITE_RANK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (new_best != old_best) {
|
||||
LL_DELETE(dodag->parents, new_best);
|
||||
LL_PREPEND(dodag->parents, new_best);
|
||||
if (dodag->instance->mop != GNRC_RPL_MOP_NO_DOWNWARD_ROUTES) {
|
||||
gnrc_rpl_send_DAO(dodag, &old_best->addr, 0);
|
||||
gnrc_rpl_send_DAO(dodag->instance, &old_best->addr, 0);
|
||||
gnrc_rpl_delay_dao(dodag);
|
||||
}
|
||||
trickle_reset_timer(&dodag->trickle);
|
||||
|
||||
fib_remove_entry(&gnrc_ipv6_fib_table, def.u8, sizeof(ipv6_addr_t));
|
||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||
|
||||
kernel_pid_t if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
|
||||
|
||||
if (if_id == KERNEL_PID_UNDEF) {
|
||||
DEBUG("RPL: no interface found for the parent addres\n");
|
||||
DEBUG("RPL: no interface found for the parent address\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fib_add_entry(&gnrc_ipv6_fib_table, if_id, def.u8, sizeof(ipv6_addr_t),
|
||||
0x0, dodag->parents->addr.u8, sizeof(ipv6_addr_t),
|
||||
FIB_FLAG_RPL_ROUTE, (dodag->default_lifetime *
|
||||
dodag->lifetime_unit) * SEC_IN_MS);
|
||||
FIB_FLAG_RPL_ROUTE, (dodag->default_lifetime * dodag->lifetime_unit)
|
||||
* SEC_IN_MS);
|
||||
}
|
||||
|
||||
dodag->my_rank = dodag->instance->of->calc_rank(dodag->parents, 0);
|
||||
if (dodag->my_rank != old_rank) {
|
||||
trickle_reset_timer(&dodag->trickle);
|
||||
}
|
||||
|
||||
elt = NULL; tmp = NULL;
|
||||
LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
|
||||
if (DAGRANK(dodag->my_rank, dodag->instance->min_hop_rank_inc)
|
||||
<= DAGRANK(elt->rank, dodag->instance->min_hop_rank_inc)) {
|
||||
gnrc_rpl_parent_remove(elt);
|
||||
}
|
||||
}
|
||||
|
||||
return dodag->parents;
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *gnrc_rpl_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_id, uint8_t mop)
|
||||
gnrc_rpl_instance_t *gnrc_rpl_root_instance_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
||||
uint8_t mop)
|
||||
{
|
||||
if (gnrc_rpl_pid == KERNEL_PID_UNDEF) {
|
||||
DEBUG("RPL: RPL thread not started\n");
|
||||
@ -464,29 +360,30 @@ gnrc_rpl_dodag_t *gnrc_rpl_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dod
|
||||
DEBUG("RPL: could not allocate memory for a new instance with id %d", instance_id);
|
||||
return NULL;
|
||||
}
|
||||
else if (inst->mop != mop) {
|
||||
DEBUG("RPL: instance (%d) exists with another MOP", instance_id);
|
||||
else {
|
||||
DEBUG("RPL: instance (%d) exists", instance_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!gnrc_rpl_dodag_add(inst, dodag_id, &dodag)) {
|
||||
DEBUG("RPL: DODAG with id %s exists or no memory left for a new DODAG",
|
||||
ipv6_addr_to_str(addr_str, dodag_id, sizeof(addr_str)));
|
||||
if (!gnrc_rpl_dodag_init(inst, dodag_id)) {
|
||||
DEBUG("RPL: could not initialize DODAG");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dodag = &inst->dodag;
|
||||
dodag->prefix_len = netif_addr->prefix_len;
|
||||
dodag->addr_preferred = netif_addr->preferred;
|
||||
dodag->addr_valid = netif_addr->valid;
|
||||
dodag->instance = inst;
|
||||
|
||||
return dodag;
|
||||
return inst;
|
||||
}
|
||||
|
||||
void gnrc_rpl_leaf_operation(gnrc_rpl_dodag_t *dodag)
|
||||
{
|
||||
dodag->node_status = GNRC_RPL_LEAF_NODE;
|
||||
/* send INFINITE_RANK DIO to current children */
|
||||
gnrc_rpl_send_DIO(dodag, NULL);
|
||||
gnrc_rpl_send_DIO(dodag->instance, NULL);
|
||||
}
|
||||
|
||||
void gnrc_rpl_router_operation(gnrc_rpl_dodag_t *dodag)
|
||||
|
||||
@ -50,9 +50,9 @@ int _gnrc_rpl_dodag_root(char *arg1, char *arg2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
dodag = gnrc_rpl_root_init(instance_id, &dodag_id, false, false);
|
||||
if (dodag == NULL) {
|
||||
gnrc_rpl_instance_t *inst = NULL;
|
||||
inst = gnrc_rpl_root_init(instance_id, &dodag_id, false, false);
|
||||
if (inst == NULL) {
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
printf("error: could not add DODAG (%s) to instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)), instance_id);
|
||||
@ -82,133 +82,60 @@ int _gnrc_rpl_instance_remove(char *arg1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gnrc_rpl_dodag_remove(char *arg1, char *arg2)
|
||||
int _gnrc_rpl_trickle_reset(char *arg1)
|
||||
{
|
||||
uint8_t instance_id = (uint8_t) atoi(arg1);
|
||||
ipv6_addr_t dodag_id;
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) {
|
||||
puts("error: <dodag_id> must be a valid IPv6 address");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) {
|
||||
puts("error: could not find the <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) {
|
||||
puts("error: <dodag_id> does not exist for the given <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
trickle_reset_timer(&(inst->dodag.trickle));
|
||||
|
||||
if (gnrc_rpl_dodag_remove(dodag) == false) {
|
||||
printf("error: could not remove DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
instance_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("success: removed DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
printf("success: reset trickle timer of DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &(inst->dodag.dodag_id), sizeof(addr_str)),
|
||||
instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gnrc_rpl_trickle_reset(char *arg1, char *arg2)
|
||||
int _gnrc_rpl_trickle_stop(char *arg1)
|
||||
{
|
||||
uint8_t instance_id = (uint8_t) atoi(arg1);
|
||||
ipv6_addr_t dodag_id;
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) {
|
||||
puts("error: <dodag_id> must be a valid IPv6 address");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) {
|
||||
puts("error: could not find the <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) {
|
||||
puts("error: <dodag_id> does not exist for the given <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
trickle_reset_timer(&dodag->trickle);
|
||||
|
||||
printf("success: resetted trickle timer of DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gnrc_rpl_trickle_stop(char *arg1, char *arg2)
|
||||
{
|
||||
uint8_t instance_id = (uint8_t) atoi(arg1);
|
||||
ipv6_addr_t dodag_id;
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) {
|
||||
puts("error: <dodag_id> must be a valid IPv6 address");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) {
|
||||
puts("error: could not find the <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) {
|
||||
puts("error: <dodag_id> does not exist for the given <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
trickle_stop(&dodag->trickle);
|
||||
trickle_stop(&(inst->dodag.trickle));
|
||||
|
||||
printf("success: stopped trickle timer of DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
ipv6_addr_to_str(addr_str, &(inst->dodag.dodag_id), sizeof(addr_str)),
|
||||
instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gnrc_rpl_trickle_start(char *arg1, char *arg2)
|
||||
int _gnrc_rpl_trickle_start(char *arg1)
|
||||
{
|
||||
uint8_t instance_id = (uint8_t) atoi(arg1);
|
||||
ipv6_addr_t dodag_id;
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) {
|
||||
puts("error: <dodag_id> must be a valid IPv6 address");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) {
|
||||
puts("error: could not find the <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) {
|
||||
puts("error: <dodag_id> does not exist for the given <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
|
||||
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
|
||||
dodag->dio_interval_doubl, dodag->dio_redun);
|
||||
trickle_start(gnrc_rpl_pid, &(inst->dodag.trickle), GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
|
||||
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << inst->dodag.dio_min),
|
||||
inst->dodag.dio_interval_doubl, inst->dodag.dio_redun);
|
||||
|
||||
printf("success: started trickle timer of DODAG (%s) from instance (%d)\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
ipv6_addr_to_str(addr_str, &(inst->dodag.dodag_id), sizeof(addr_str)),
|
||||
instance_id);
|
||||
return 0;
|
||||
}
|
||||
@ -240,22 +167,6 @@ int _gnrc_rpl_dodag_show(void)
|
||||
}
|
||||
}
|
||||
|
||||
printf("dodag table:\t");
|
||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||
if (gnrc_rpl_dodags[i].state == 0) {
|
||||
printf("[ ]");
|
||||
}
|
||||
else {
|
||||
printf("[X]");
|
||||
}
|
||||
if (i < (GNRC_RPL_DODAGS_NUMOF - 1)) {
|
||||
putchar('\t');
|
||||
}
|
||||
else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("parent table:\t");
|
||||
for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) {
|
||||
if (gnrc_rpl_parents[i].state == 0) {
|
||||
@ -283,76 +194,56 @@ int _gnrc_rpl_dodag_show(void)
|
||||
printf("instance [%d | mop: %d | ocp: %d | mhri: %d | mri %d]\n", gnrc_rpl_instances[i].id,
|
||||
gnrc_rpl_instances[i].mop, gnrc_rpl_instances[i].of->ocp,
|
||||
gnrc_rpl_instances[i].min_hop_rank_inc, gnrc_rpl_instances[i].max_rank_inc);
|
||||
LL_FOREACH(gnrc_rpl_instances[i].dodags, dodag) {
|
||||
|
||||
tc = (((uint64_t) dodag->trickle.msg_callback_timer.long_target << 32)
|
||||
| dodag->trickle.msg_callback_timer.target) - xnow;
|
||||
tc = (int64_t) tc < 0 ? 0 : tc / SEC_IN_USEC;
|
||||
dodag = &gnrc_rpl_instances[i].dodag;
|
||||
|
||||
ti = (((uint64_t) dodag->trickle.msg_interval_timer.long_target << 32)
|
||||
| dodag->trickle.msg_interval_timer.target) - xnow;
|
||||
ti = (int64_t) ti < 0 ? 0 : ti / SEC_IN_USEC;
|
||||
tc = (((uint64_t) dodag->trickle.msg_callback_timer.long_target << 32)
|
||||
| dodag->trickle.msg_callback_timer.target) - xnow;
|
||||
tc = (int64_t) tc < 0 ? 0 : tc / SEC_IN_USEC;
|
||||
|
||||
cleanup = dodag->cleanup_timer.target - xtimer_now();
|
||||
cleanup = (int32_t) cleanup < 0 ? 0 : cleanup / SEC_IN_USEC;
|
||||
ti = (((uint64_t) dodag->trickle.msg_interval_timer.long_target << 32)
|
||||
| dodag->trickle.msg_interval_timer.target) - xnow;
|
||||
ti = (int64_t) ti < 0 ? 0 : ti / SEC_IN_USEC;
|
||||
|
||||
printf("\tdodag [%s | R: %d | OP: %s | CL: %" PRIu32 "s | "
|
||||
"TR(I=[%d,%d], k=%d, c=%d, TC=%" PRIu64 "s, TI=%" PRIu64 "s)]\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag->dodag_id, sizeof(addr_str)),
|
||||
dodag->my_rank, (dodag->node_status == GNRC_RPL_LEAF_NODE ? "Leaf" : "Router"),
|
||||
cleanup, (1 << dodag->dio_min), dodag->dio_interval_doubl, dodag->trickle.k,
|
||||
dodag->trickle.c, tc, ti);
|
||||
gnrc_rpl_parent_t *parent;
|
||||
LL_FOREACH(dodag->parents, parent) {
|
||||
printf("\t\tparent [addr: %s | rank: %d | lifetime: %" PRIu64 "s]\n",
|
||||
ipv6_addr_to_str(addr_str, &parent->addr, sizeof(addr_str)),
|
||||
parent->rank, ((int64_t) (parent->lifetime - xnow) < 0 ? 0
|
||||
: (parent->lifetime - xnow) / SEC_IN_USEC));
|
||||
}
|
||||
cleanup = dodag->cleanup_timer.target - xtimer_now();
|
||||
cleanup = (int32_t) cleanup < 0 ? 0 : cleanup / SEC_IN_USEC;
|
||||
|
||||
printf("\tdodag [%s | R: %d | OP: %s | CL: %" PRIu32 "s | "
|
||||
"TR(I=[%d,%d], k=%d, c=%d, TC=%" PRIu64 "s, TI=%" PRIu64 "s)]\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag->dodag_id, sizeof(addr_str)),
|
||||
dodag->my_rank, (dodag->node_status == GNRC_RPL_LEAF_NODE ? "Leaf" : "Router"),
|
||||
cleanup, (1 << dodag->dio_min), dodag->dio_interval_doubl, dodag->trickle.k,
|
||||
dodag->trickle.c, tc, ti);
|
||||
|
||||
gnrc_rpl_parent_t *parent;
|
||||
LL_FOREACH(gnrc_rpl_instances[i].dodag.parents, parent) {
|
||||
printf("\t\tparent [addr: %s | rank: %d | lifetime: %" PRIu64 "s]\n",
|
||||
ipv6_addr_to_str(addr_str, &parent->addr, sizeof(addr_str)),
|
||||
parent->rank, ((int64_t) (parent->lifetime - xnow) < 0 ? 0
|
||||
: (parent->lifetime - xnow) / SEC_IN_USEC));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gnrc_rpl_operation(bool leaf, char *arg1, char *arg2)
|
||||
int _gnrc_rpl_operation(bool leaf, char *arg1)
|
||||
{
|
||||
uint8_t instance_id = 0;
|
||||
ipv6_addr_t dodag_id;
|
||||
uint8_t instance_id = (uint8_t) atoi(arg1);
|
||||
gnrc_rpl_instance_t *inst;
|
||||
gnrc_rpl_dodag_t *dodag = NULL;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
instance_id = (uint8_t) atoi(arg1);
|
||||
if (instance_id == 0) {
|
||||
puts("error: <instance_id> must be a positive number greater than zero");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) {
|
||||
puts("error: <dodag_id> must be a valid IPv6 address");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) {
|
||||
puts("error: could not find the <instance_id>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) {
|
||||
puts("error: <dodag_id> does not exist for the given <instance_id>");
|
||||
printf("error: could not find the instance (%d)\n", instance_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (leaf) {
|
||||
gnrc_rpl_leaf_operation(dodag);
|
||||
gnrc_rpl_leaf_operation(&inst->dodag);
|
||||
}
|
||||
else {
|
||||
gnrc_rpl_router_operation(dodag);
|
||||
gnrc_rpl_router_operation(&inst->dodag);
|
||||
}
|
||||
|
||||
printf("success: operate in DODAG (%s) from instance (%d) as %s\n",
|
||||
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)),
|
||||
instance_id, leaf ? "leaf" : "router");
|
||||
printf("success: operate in instance (%d) as %s\n", instance_id, leaf ? "leaf" : "router");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -368,22 +259,19 @@ int _gnrc_rpl(int argc, char **argv)
|
||||
return _gnrc_rpl_dodag_root(argv[2], argv[3]);
|
||||
}
|
||||
else if (strcmp(argv[1], "rm") == 0) {
|
||||
if (argc == 4) {
|
||||
return _gnrc_rpl_dodag_remove(argv[2], argv[3]);
|
||||
}
|
||||
else if (argc == 3) {
|
||||
if (argc == 3) {
|
||||
return _gnrc_rpl_instance_remove(argv[2]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "trickle") == 0) {
|
||||
if ((argc == 5) && (strcmp(argv[2], "reset") == 0)) {
|
||||
return _gnrc_rpl_trickle_reset(argv[3], argv[4]);
|
||||
if ((argc == 4) && (strcmp(argv[2], "reset") == 0)) {
|
||||
return _gnrc_rpl_trickle_reset(argv[3]);
|
||||
}
|
||||
else if ((argc == 5) && (strcmp(argv[2], "stop") == 0)) {
|
||||
return _gnrc_rpl_trickle_stop(argv[3], argv[4]);
|
||||
else if ((argc == 4) && (strcmp(argv[2], "stop") == 0)) {
|
||||
return _gnrc_rpl_trickle_stop(argv[3]);
|
||||
}
|
||||
else if ((argc == 5) && (strcmp(argv[2], "start") == 0)) {
|
||||
return _gnrc_rpl_trickle_start(argv[3], argv[4]);
|
||||
else if ((argc == 4) && (strcmp(argv[2], "start") == 0)) {
|
||||
return _gnrc_rpl_trickle_start(argv[3]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "send") == 0) {
|
||||
@ -392,29 +280,27 @@ int _gnrc_rpl(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "leaf") == 0) {
|
||||
if (argc == 4) {
|
||||
return _gnrc_rpl_operation(true, argv[2], argv[3]);
|
||||
if (argc == 3) {
|
||||
return _gnrc_rpl_operation(true, argv[2]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "router") == 0) {
|
||||
if (argc == 4) {
|
||||
return _gnrc_rpl_operation(false, argv[2], argv[3]);
|
||||
if (argc == 3) {
|
||||
return _gnrc_rpl_operation(false, argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("usage: %s [help|init|rm|root|show]\n", argv[0]);
|
||||
puts("* help\t\t\t\t\t\t- show usage");
|
||||
puts("* init <if_id>\t\t\t\t\t- initialize RPL on the given interface");
|
||||
puts("* leaf <instance_id> <dodag_id>\t\t\t- operate as leaf in the dodag");
|
||||
puts("* trickle reset <instance_id> <dodag_id>\t- reset the trickle timer");
|
||||
puts("* trickle start <instance_id> <dodag_id>\t- start the trickle timer");
|
||||
puts("* trickle stop <instance_id> <dodag_id>\t\t- stop the trickle timer");
|
||||
puts("* rm <instance_id>\t\t\t\t- delete the given instance and all related dodags");
|
||||
puts("* rm <instance_id> <dodag_id>\t\t\t- delete the dodag in the given instance");
|
||||
puts("* root <instance_id> <dodag_id>\t\t\t- add a dodag to a new or existing instance");
|
||||
puts("* router <instance_id> <dodag_id>\t\t\t- operate as router in the dodag");
|
||||
puts("* send dis\t\t\t\t\t- send a multicast DIS");
|
||||
puts("* show\t\t\t\t\t\t- show instance and dodag tables");
|
||||
puts("* help\t\t\t\t- show usage");
|
||||
puts("* init <if_id>\t\t\t- initialize RPL on the given interface");
|
||||
puts("* leaf <instance_id>\t\t- operate as leaf in the instance");
|
||||
puts("* trickle reset <instance_id>\t- reset the trickle timer");
|
||||
puts("* trickle start <instance_id>\t- start the trickle timer");
|
||||
puts("* trickle stop <instance_id>\t- stop the trickle timer");
|
||||
puts("* rm <instance_id>\t\t- delete the given instance and related dodag");
|
||||
puts("* root <inst_id> <dodag_id>\t- add a dodag to a new or existing instance");
|
||||
puts("* router <instance_id>\t\t- operate as router in the instance");
|
||||
puts("* send dis\t\t\t- send a multicast DIS");
|
||||
puts("* show\t\t\t\t- show instance and dodag tables");
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user