Exemplo n.º 1
0
rpl_parent_t *rpl_find_preferred_parent(void)
{
    rpl_parent_t *best = NULL;
    rpl_dodag_t *my_dodag = rpl_get_my_dodag();

    if (my_dodag == NULL) {
        DEBUG("Not part of a dodag\n");
        return NULL;
    }

    for (uint8_t i = 0; i < RPL_MAX_PARENTS; i++) {
        if (parents[i].used) {
            if ((parents[i].rank == INFINITE_RANK) || (parents[i].lifetime <= 1)) {
                DEBUG("Infinite rank, bad parent\n");
                continue;
            }
            else if (best == NULL) {
                DEBUG("possible parent\n");
                best = &parents[i];
            }
            else {
                best = my_dodag->of->which_parent(best, &parents[i]);
            }
        }
    }

    if (best == NULL) {
        return NULL;
    }

    if (my_dodag->my_preferred_parent == NULL) {
        my_dodag->my_preferred_parent = best;
    }

    if (!rpl_equal_id(&my_dodag->my_preferred_parent->addr, &best->addr)) {
        if (my_dodag->mop != NO_DOWNWARD_ROUTES) {
            /* send DAO with ZERO_LIFETIME to old parent */
            send_DAO(&my_dodag->my_preferred_parent->addr, 0, false, 0);
        }

        my_dodag->my_preferred_parent = best;

        if (my_dodag->mop != NO_DOWNWARD_ROUTES) {
            delay_dao();
        }

        reset_trickletimer();
    }

    return best;
}
Exemplo n.º 2
0
void dao_delay_over(void)
{
    while (1) {
        thread_sleep();

        if ((ack_received == false) && (dao_counter < DAO_SEND_RETRIES)) {
            dao_counter++;
            send_DAO(NULL, 0, true, 0);
            dao_time = timex_set(DEFAULT_WAIT_FOR_DAO_ACK, 0);
            vtimer_remove(&dao_timer);
            vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid);
        }
        else if (ack_received == false) {
            long_delay_dao();
        }
    }
}
Exemplo n.º 3
0
Arquivo: rpl.c Projeto: hper/RIOT
void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index)
{
    if (i_am_root) {
        return;
    }

    mutex_lock(&rpl_send_mutex);
    rpl_dodag_t *my_dodag;
    my_dodag = rpl_get_my_dodag();

    if (destination == NULL) {
        destination = &my_dodag->my_preferred_parent->addr;
    }

    if (default_lifetime) {
        lifetime = my_dodag->default_lifetime;
    }

    icmp_send_buf  = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len);

    icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL;
    icmp_send_buf->code = ICMP_CODE_DAO;
    icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6);

    if (my_dodag == NULL) {
        mutex_unlock(&rpl_send_mutex);
        return;
    }

    rpl_send_dao_buf = get_rpl_send_dao_buf();
    memset(rpl_send_dao_buf, 0, sizeof(*rpl_send_dao_buf));
    rpl_send_dao_buf->rpl_instanceid = my_dodag->instance->id;
    rpl_send_dao_buf->k_d_flags = 0x00;
    rpl_send_dao_buf->dao_sequence = my_dodag->dao_seq;
    uint16_t opt_len = 0;
    rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN);
    /* add all targets from routing table as targets */
    uint8_t entries = 0;
    uint8_t continue_index = 0;

    for (uint8_t i = start_index; i < RPL_MAX_ROUTING_ENTRIES; i++) {
        if (routing_table[i].used) {
            rpl_send_opt_target_buf->type = RPL_OPT_TARGET;
            rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN;
            rpl_send_opt_target_buf->flags = 0x00;
            rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN;
            memcpy(&rpl_send_opt_target_buf->target, &routing_table[i].address, sizeof(ipv6_addr_t));
            opt_len += RPL_OPT_TARGET_LEN + 2;
            rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len);
            rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT;
            rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN;
            rpl_send_opt_transit_buf->e_flags = 0x00;
            rpl_send_opt_transit_buf->path_control = 0x00; /* not used */
            rpl_send_opt_transit_buf->path_sequence = 0x00; /* not used */
            rpl_send_opt_transit_buf->path_lifetime = lifetime;
            opt_len += RPL_OPT_TRANSIT_LEN + 2;
            rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN + opt_len);
            entries++;
        }

        /* Split DAO, so packages don't get too big.
         * The value 5 is based on experience. */
        if (entries >= 5) {
            continue_index = i + 1;
            break;
        }
    }

    /* add own address */
    rpl_send_opt_target_buf->type = RPL_OPT_TARGET;
    rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN;
    rpl_send_opt_target_buf->flags = 0x00;
    rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN;
    memcpy(&rpl_send_opt_target_buf->target, &my_address, sizeof(ipv6_addr_t));
    opt_len += RPL_OPT_TARGET_LEN + 2;

    rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len);
    rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT;
    rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN;
    rpl_send_opt_transit_buf->e_flags = 0x00;
    rpl_send_opt_transit_buf->path_control = 0x00;
    rpl_send_opt_transit_buf->path_sequence = 0x00;
    rpl_send_opt_transit_buf->path_lifetime = lifetime;
    opt_len += RPL_OPT_TRANSIT_LEN + 2;

    uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len;
    rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL);
    mutex_unlock(&rpl_send_mutex);

    if (continue_index > 1) {
        send_DAO(destination, lifetime, default_lifetime, continue_index);
    }
}