Exemplo n.º 1
0
static void thread_parse_child_update_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
{
    uint8_t mode;
    uint32_t timeout;
    mle_neigh_table_entry_t *entry_temp;
    thread_leader_data_t leaderData = {0};
    uint8_t status;
    bool leader_data_received;

    tr_debug("Child Update Response");

    leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
    entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);

    if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) &&
        status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) {
        tr_debug("parent has connection error");
        thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
        return;
    }

    if (!entry_temp) {
        tr_debug("Not Neighbor");
        mle_tlv_info_t challengeTlv;
        mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
        thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
        return;
    }

    if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
            && (thread_instance_id_matches(cur, &leaderData))) {
        thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
    } else {
        tr_debug("Key ID Mode 2 not used; dropped.");
        return;
    }

    if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
        tr_debug("No Mode");
        return;
    }

    if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
        entry_temp->holdTime = 90;
        tr_debug("Setting child timeout, value=%"PRIu32, timeout);
        mle_entry_timeout_update(entry_temp, timeout);
        thread_info(cur)->thread_endnode_parent->childUpdateProcessStatus = true;
    }
    tr_debug("Keep-Alive -->Respond from Parent");
    mle_entry_timeout_refresh(entry_temp);

    //Save possible new Leader Data
    if (leader_data_received) {
        thread_save_leader_data(cur, &leaderData);
    }
    mac_data_poll_protocol_poll_mode_decrement(cur);
}
Exemplo n.º 2
0
void nwk_parent_poll_fail_cb(int8_t id)
{
    protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(id);
    if (!cur) {
        tr_error("Data Poll Fail Event: No interface");
        return;
    }
    if (thread_info(cur)) {
        //Initialize Bootsrap
        thread_bootstrap_connection_error(cur->id, CON_ERROR_POLL, NULL);
    } else {
        nwk_bootsrap_state_update(ARM_NWK_NWK_PARENT_POLL_FAIL, cur);
    }

}
Exemplo n.º 3
0
static bool thread_reed_partitions_merge(protocol_interface_info_entry_t *cur, uint16_t shortAddress, thread_leader_data_t heard_partition_leader_data)
{
    if (thread_is_router_addr(shortAddress)) {
        return false;
    }
    if (thread_extension_version_check(thread_info(cur)->version)) {
        // lower weighting heard
        if (thread_info(cur)->thread_leader_data->weighting > heard_partition_leader_data.weighting) {
            return false;
        }
        // lower/same partition id heard
        if (thread_info(cur)->thread_leader_data->weighting == heard_partition_leader_data.weighting &&
                thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId ) {
            return false;
        }
    } else if (thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId){
        return false;
    }
    // can merge to a higher weighting/partition id
    thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
    return true;
}
Exemplo n.º 4
0
static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor)
{
    int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv);

    if (leaderDataUpdate == 1) {
        if (neighbor && neighbor->handshakeReady == 1) {
            // Request network data if we have a 2-way link
            tr_debug("Request New Network Data from %s", trace_ipv6(src_address));
            thread_network_data_request_send(cur, src_address, true);
        } else {

        }
    } else if (leaderDataUpdate == 2) {
        tr_debug("Start Merge");
        thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
        return false;

    } else if (leaderDataUpdate < 0) {
        tr_warn("Leader data failure");
        return false;
    }
    return true;
}
Exemplo n.º 5
0
static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
{
    mle_tlv_info_t routeTlv;
    thread_leader_data_t leaderData;
    uint16_t shortAddress;
    mle_neigh_table_entry_t *entry_temp;

    // Check device mode & bootstrap state
    if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) ||
        (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) {
        return;
    }

    tr_debug("Received Advertisement");

    // Validate and parse TLV's
    if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) {
        return;
    }

    // Get MLE entry
    entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);

    if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
            && (thread_instance_id_matches(cur, &leaderData))) {
        thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
    }

    // Check parent status
    if (!thread_attach_active_router(cur)) {
        //processing for non routers
        if (thread_check_is_this_my_parent(cur, entry_temp)) {
            //advertisement from parent
            if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) ||
                (thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) {
                //parent changed partition/weight - reset own routing information
                thread_old_partition_data_purge(cur);
            }
            //check if network data needs to be requested
            if (!thread_bootstrap_request_network_data(cur, &leaderData, shortAddress)) {
                tr_debug("Parent short address changed - re-attach");
                thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
                return;
            }
        }
    }

    // Update MLE entry
    thread_update_mle_entry(cur, mle_msg, security_headers, entry_temp, shortAddress);

    // Process advertisement
    if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
        if (!thread_attach_active_router(cur)) {
            // REED and FED
            if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
                if ((thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) &&
                        (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting)) {
                    // Create link to new neighbor no other processing allowed
                    thread_link_request_start(cur, mle_msg->packet_src_address);
                    return;
                }
                if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp)) {
                    // better partition found or new network data learn started
                    return;
                }
            }
            // process REED advertisement from higher partition
            if (thread_reed_partitions_merge(cur, shortAddress, leaderData)) {
                return;
            }
        } else {
            //Router
            if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) {
                return;
            }
            thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress);
        }
    }

    // Process route TLV
    if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) &&
            (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){
        tr_debug("Update Route TLV %x", entry_temp->short_adr);
        thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp);
    }
}