diff --git a/sys/include/net/gnrc/rpl.h b/sys/include/net/gnrc/rpl.h index a2b9015582..b45bd0763d 100644 --- a/sys/include/net/gnrc/rpl.h +++ b/sys/include/net/gnrc/rpl.h @@ -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 + * RFC 6550, section 3.5.1, Rank Comparison (DAGRank()) + * + */ +#define DAGRANK(rank,mhri) (rank/mhri) + /** * @name Global / Local instance id masks * @see @@ -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 diff --git a/sys/include/net/gnrc/rpl/dodag.h b/sys/include/net/gnrc/rpl/dodag.h index 8a6bf0a5ae..10a73b8e25 100644 --- a/sys/include/net/gnrc/rpl/dodag.h +++ b/sys/include/net/gnrc/rpl/dodag.h @@ -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. * diff --git a/sys/include/net/gnrc/rpl/structs.h b/sys/include/net/gnrc/rpl/structs.h index 87e7e3d7c8..0a3f3ccec1 100644 --- a/sys/include/net/gnrc/rpl/structs.h +++ b/sys/include/net/gnrc/rpl/structs.h @@ -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 diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl.c b/sys/net/gnrc/routing/rpl/gnrc_rpl.c index 7f11e6407f..670a6cba02 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl.c @@ -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); } diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c index 5d2b344d61..9af2284e23 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c @@ -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", diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c index f6e90e6add..a352650e0d 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c @@ -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) diff --git a/sys/shell/commands/sc_gnrc_rpl.c b/sys/shell/commands/sc_gnrc_rpl.c index 9c75f2e65a..053967a02d 100644 --- a/sys/shell/commands/sc_gnrc_rpl.c +++ b/sys/shell/commands/sc_gnrc_rpl.c @@ -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: must be a valid IPv6 address"); - return 1; - } - if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) { puts("error: could not find the "); return 1; } - if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) { - puts("error: does not exist for the given "); - 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: must be a valid IPv6 address"); - return 1; - } - if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) { puts("error: could not find the "); return 1; } - - if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) { - puts("error: does not exist for the given "); - 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: must be a valid IPv6 address"); - return 1; - } - - if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) { - puts("error: could not find the "); - return 1; - } - - if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) { - puts("error: does not exist for the given "); - 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: must be a valid IPv6 address"); - return 1; - } - if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) { puts("error: could not find the "); return 1; } - if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) { - puts("error: does not exist for the given "); - 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: must be a positive number greater than zero"); - return 1; - } - - if (ipv6_addr_from_str(&dodag_id, arg2) == NULL) { - puts("error: must be a valid IPv6 address"); - return 1; - } if ((inst = gnrc_rpl_instance_get(instance_id)) == NULL) { - puts("error: could not find the "); - return 1; - } - - if ((dodag = gnrc_rpl_dodag_get(inst, &dodag_id)) == NULL) { - puts("error: does not exist for the given "); + 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 \t\t\t\t\t- initialize RPL on the given interface"); - puts("* leaf \t\t\t- operate as leaf in the dodag"); - puts("* trickle reset \t- reset the trickle timer"); - puts("* trickle start \t- start the trickle timer"); - puts("* trickle stop \t\t- stop the trickle timer"); - puts("* rm \t\t\t\t- delete the given instance and all related dodags"); - puts("* rm \t\t\t- delete the dodag in the given instance"); - puts("* root \t\t\t- add a dodag to a new or existing instance"); - puts("* router \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 \t\t\t- initialize RPL on the given interface"); + puts("* leaf \t\t- operate as leaf in the instance"); + puts("* trickle reset \t- reset the trickle timer"); + puts("* trickle start \t- start the trickle timer"); + puts("* trickle stop \t- stop the trickle timer"); + puts("* rm \t\t- delete the given instance and related dodag"); + puts("* root \t- add a dodag to a new or existing instance"); + puts("* router \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; } /**