kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid) { /* check if RPL was initialized before */ if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { /* start the event loop */ gnrc_rpl_pid = thread_create(_stack, sizeof(_stack), GNRC_RPL_PRIO, CREATE_STACKTEST, _event_loop, NULL, "RPL"); if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { DEBUG("RPL: could not start the event loop\n"); return KERNEL_PID_UNDEF; } _me_reg.demux_ctx = ICMPV6_RPL_CTRL; _me_reg.pid = gnrc_rpl_pid; /* register interest in all ICMPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &_me_reg); gnrc_rpl_of_manager_init(); _lt_time = timex_set(GNRC_RPL_LIFETIME_UPDATE_STEP, 0); vtimer_set_msg(&_lt_timer, _lt_time, gnrc_rpl_pid, GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE, NULL); } /* register all_RPL_nodes multicast address */ ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR; gnrc_ipv6_netif_add_addr(if_pid, &all_RPL_nodes, IPV6_ADDR_BIT_LEN, 0); gnrc_rpl_send_DIS(NULL, &all_RPL_nodes); return gnrc_rpl_pid; }
kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid) { /* check if RPL was initialized before */ if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { _instance_id = 0; /* start the event loop */ gnrc_rpl_pid = thread_create(_stack, sizeof(_stack), GNRC_RPL_PRIO, THREAD_CREATE_STACKTEST, _event_loop, NULL, "RPL"); if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { DEBUG("RPL: could not start the event loop\n"); return KERNEL_PID_UNDEF; } _me_reg.demux_ctx = ICMPV6_RPL_CTRL; _me_reg.target.pid = gnrc_rpl_pid; /* register interest in all ICMPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &_me_reg); gnrc_rpl_of_manager_init(); xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid); #ifdef MODULE_NETSTATS_RPL memset(&gnrc_rpl_netstats, 0, sizeof(gnrc_rpl_netstats)); #endif } /* register all_RPL_nodes multicast address */ gnrc_ipv6_netif_add_addr(if_pid, &ipv6_addr_all_rpl_nodes, IPV6_ADDR_BIT_LEN, 0); gnrc_rpl_send_DIS(NULL, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes); return gnrc_rpl_pid; }
void _update_lifetime(void) { uint32_t now = xtimer_now(); uint16_t now_sec = now / SEC_IN_USEC; gnrc_rpl_parent_t *parent; gnrc_rpl_instance_t *inst; for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) { parent = &gnrc_rpl_parents[i]; if (parent->state != 0) { if ((int32_t)(parent->lifetime - now_sec) <= GNRC_RPL_LIFETIME_UPDATE_STEP) { gnrc_rpl_dodag_t *dodag = parent->dodag; gnrc_rpl_parent_remove(parent); gnrc_rpl_parent_update(dodag, NULL); continue; } else if ((int32_t)(parent->lifetime - now_sec) <= (GNRC_RPL_LIFETIME_UPDATE_STEP * 2)) { gnrc_rpl_send_DIS(parent->dodag->instance, &parent->addr); } } } for (int i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) { inst = &gnrc_rpl_instances[i]; if (inst->state != 0) { if ((inst->cleanup > 0) && (inst->dodag.parents == NULL) && (inst->dodag.my_rank == GNRC_RPL_INFINITE_RANK)) { inst->cleanup -= GNRC_RPL_LIFETIME_UPDATE_STEP; if (inst->cleanup <= 0) { /* no parents - delete this instance and DODAG */ gnrc_rpl_instance_remove(inst); continue; } } if (inst->dodag.dao_time > GNRC_RPL_LIFETIME_UPDATE_STEP) { inst->dodag.dao_time -= GNRC_RPL_LIFETIME_UPDATE_STEP; } else { _dao_handle_send(&inst->dodag); } } } #ifdef MODULE_GNRC_RPL_P2P gnrc_rpl_p2p_update(); #endif xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid); }
void _update_lifetime(void) { uint64_t now = xtimer_now64(); gnrc_rpl_parent_t *parent; for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) { parent = &gnrc_rpl_parents[i]; if (parent->state != 0) { if ((int64_t)(parent->lifetime - now) <= (int64_t) (GNRC_RPL_LIFETIME_UPDATE_STEP * SEC_IN_USEC)) { gnrc_rpl_dodag_t *dodag = parent->dodag; gnrc_rpl_parent_remove(parent); gnrc_rpl_parent_update(dodag, NULL); continue; } 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); } } } xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid); }
void _update_lifetime(void) { timex_t now; vtimer_now(&now); gnrc_rpl_parent_t *parent; for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) { parent = &gnrc_rpl_parents[i]; if (parent->state != 0) { if ((signed)(parent->lifetime.seconds - now.seconds) <= GNRC_RPL_LIFETIME_UPDATE_STEP) { gnrc_rpl_dodag_t *dodag = parent->dodag; gnrc_rpl_parent_remove(parent); gnrc_rpl_parent_update(dodag, NULL); continue; } else if (((signed)(parent->lifetime.seconds - now.seconds) <= GNRC_RPL_LIFETIME_UPDATE_STEP * 2)) { gnrc_rpl_send_DIS(parent->dodag, &parent->addr); } } } vtimer_remove(&_lt_timer); vtimer_set_msg(&_lt_timer, _lt_time, gnrc_rpl_pid, GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE, NULL); }
void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src, uint16_t len) { gnrc_rpl_instance_t *inst = NULL; gnrc_rpl_dodag_t *dodag = NULL; if (!_gnrc_rpl_check_DIO_validity(dio, len)) { return; } 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); if (iface == KERNEL_PID_UNDEF) { iface = gnrc_ipv6_netif_find_by_addr(NULL, &ipv6_addr_all_rpl_nodes); assert(iface != KERNEL_PID_UNDEF); } gnrc_rpl_dodag_init(inst, &dio->dodag_id, iface, NULL); dodag = &inst->dodag; DEBUG("RPL: Joined DODAG (%s).\n", ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str))); 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_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, inst, (gnrc_rpl_opt_t *)(dio + 1), len, src, &included_opts)) { DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n"); gnrc_rpl_instance_remove(inst); return; } if (!(included_opts & (((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF))) { #ifndef GNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN DEBUG("RPL: DIO without DODAG_CONF option - remove DODAG and request new DIO\n"); gnrc_rpl_instance_remove(inst); gnrc_rpl_send_DIS(NULL, src); return; #else DEBUG("RPL: DIO without DODAG_CONF option - use default trickle parameters\n"); gnrc_rpl_send_DIS(NULL, src); #endif } /* if there was no netif_addr created manually or by a PIO, then leave this DODAG */ if (!dodag->netif_addr) { ipv6_addr_t *configured_addr; if (!(configured_addr = gnrc_ipv6_netif_match_prefix(dodag->iface, &dodag->dodag_id))) { DEBUG("RPL: no IPv6 address configured to match the given dodag id: %s\n", ipv6_addr_to_str(addr_str, &(dodag->dodag_id), sizeof(addr_str))); gnrc_rpl_instance_remove(inst); return; } if (!(dodag->netif_addr = gnrc_ipv6_netif_addr_get(configured_addr))) { DEBUG("RPL: no netif address found for %s\n", ipv6_addr_to_str(addr_str, configured_addr, sizeof(addr_str))); gnrc_rpl_instance_remove(inst); return; } } gnrc_rpl_delay_dao(dodag); 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); gnrc_rpl_parent_update(dodag, parent); return; } else if (inst == NULL) {