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); }
static void *_event_loop(void *args) { msg_t msg, reply; (void)args; msg_init_queue(_msg_q, GNRC_RPL_MSG_QUEUE_SIZE); /* preinitialize ACK */ reply.type = GNRC_NETAPI_MSG_TYPE_ACK; trickle_t *trickle; gnrc_rpl_dodag_t *dodag; /* start event loop */ while (1) { DEBUG("RPL: waiting for incoming message.\n"); msg_receive(&msg); switch (msg.type) { case GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE: DEBUG("RPL: GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE received\n"); _update_lifetime(); break; case GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL: DEBUG("RPL: GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL received\n"); trickle = (trickle_t *) msg.content.ptr; if (trickle && (trickle->callback.func != NULL)) { trickle_interval(trickle); } break; case GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK: DEBUG("RPL: GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK received\n"); trickle = (trickle_t *) msg.content.ptr; if (trickle && (trickle->callback.func != NULL)) { trickle_callback(trickle); } 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)) { _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)) { /* no parents - delete this DODAG */ gnrc_rpl_dodag_remove(dodag); } break; case GNRC_NETAPI_MSG_TYPE_RCV: DEBUG("RPL: GNRC_NETAPI_MSG_TYPE_RCV received\n"); _receive((gnrc_pktsnip_t *)msg.content.ptr); break; case GNRC_NETAPI_MSG_TYPE_SND: case GNRC_NETAPI_MSG_TYPE_GET: case GNRC_NETAPI_MSG_TYPE_SET: DEBUG("RPL: reply to unsupported recv/get/set\n"); reply.content.value = -ENOTSUP; msg_reply(&msg, &reply); break; default: break; } } return NULL; }
void *rpl_process(void *arg) { (void) arg; msg_t m_recv; msg_init_queue(rpl_msg_queue, RPL_PKT_RECV_BUF_SIZE); rpl_dodag_t *dodag; trickle_t *trickle; while (1) { msg_receive(&m_recv); if (m_recv.type > ICMP_CODE_END) { switch (m_recv.type) { case RPL_MSG_TYPE_DAO_HANDLE: dodag = (rpl_dodag_t *) m_recv.content.ptr; if (dodag->joined) { _dao_handle_send(dodag); } break; case RPL_MSG_TYPE_ROUTING_ENTRY_UPDATE: _rpl_update_routing_table(); break; case RPL_MSG_TYPE_TRICKLE_INTERVAL: trickle = (trickle_t *) m_recv.content.ptr; if (trickle->callback.func != NULL) { trickle_interval(trickle); } break; case RPL_MSG_TYPE_TRICKLE_CALLBACK: trickle = (trickle_t *) m_recv.content.ptr; if (trickle->callback.func != NULL) { trickle_callback(trickle); } break; default: break; } } /* This is an RPL-related message. */ else { /* differentiate packet types */ ipv6_buf = (ipv6_hdr_t *) m_recv.content.ptr; memcpy(&rpl_buffer, ipv6_buf, NTOHS(ipv6_buf->length) + IPV6_HDR_LEN); if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) { /* get code for message-interpretation and process message */ DEBUGF("Received RPL information of type %04X and length %u\n", m_recv.type, NTOHS(ipv6_buf->length)); switch (m_recv.type) { case (ICMP_CODE_DIS): { rpl_recv_DIS(); break; } case (ICMP_CODE_DIO): { rpl_recv_DIO(); break; } case (ICMP_CODE_DAO): { rpl_recv_DAO(); break; } case (ICMP_CODE_DAO_ACK): { rpl_recv_DAO_ACK(); break; } default: break; } } #if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE /* If the message is not RPL-type, it relates to non-storing mode */ else if (RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE) { if (ipv6_buf->nextheader == IPV6_PROTO_NUM_SRH) { srh_header = ((ipv6_srh_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); /* if there are no segments left, the routing is finished */ if (srh_header->segments_left == 0) { DEBUGF("Source routing finished with next header: %02X.\n", srh_header->nextheader); DEBUGF("Size of srh: %d\n", srh_header->hdrextlen); uint8_t *payload = ((uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN + sizeof(ipv6_srh_t) + srh_header->hdrextlen)); rpl_remove_srh_header(ipv6_buf, payload, srh_header->nextheader); } else { internal_srh_process(srh_header); if (down_next_hop != NULL) { uint8_t *payload = ((uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); rpl_srh_sendto(payload, NTOHS(ipv6_buf->length), &ipv6_buf->srcaddr, down_next_hop, srh_header, 0); } } } #if RPL_MAX_ROUTING_ENTRIES != 0 else { srh_header = rpl_get_srh_header(ipv6_buf); if (srh_header != NULL) { uint8_t *payload = ((uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); rpl_srh_sendto(payload, NTOHS(ipv6_buf->length), &ipv6_buf->srcaddr, &ipv6_buf->destaddr, srh_header, srh_header->hdrextlen + sizeof(ipv6_srh_t)); } } #endif } #endif } } }