Merge commit '8e546a301f0b93dab28e7b4454df97e5f9e83843'

* commit '8e546a301f0b93dab28e7b4454df97e5f9e83843':
  Squashed 'features/nanostack/sal-stack-nanostack/' changes from 43c7ec2..82bbdcc
pull/6876/head
Juhani Puurula 2018-05-11 09:52:10 +03:00
commit 2f0bd6b6f6
62 changed files with 848 additions and 509 deletions

View File

@ -995,6 +995,7 @@ extern void net_get_version_information(uint8_t *ptr);
*
* Note! In Thread mode parent buffer size is automatically set during Thread initialization.
*
* \param interface_id Network interface ID.
* \param big_packet_threshold Indicate how long packets are considered big. For Thread, must be 106 bytes.
* \param small_packets_per_child_count Number of small packets stored for each sleepy children. For Thread, must be at least 1.
* \param big_packets_total_count Total number of big packets parent can store for all sleepy children. For Thread, must be at least 1.

View File

@ -24,6 +24,7 @@
#define NET_TEST_API_H_
#include "ns_types.h"
#include "Service_Libs/mle_service/mle_service_api.h"
/**
* \brief Makes TCP protocol drop given number of packets from a particular state (TX side).
@ -56,4 +57,11 @@ int8_t arm_nwk_test_tcp_drop_rx(int state, uint8_t count);
*/
void arm_nwk_test_tcp_drop_reset(void);
/**
* \brief Set callback for MLE message receiving filter.
*
* Testing API for setting MLE receive callback for message filtering purposes.
*/
void arm_nwk_test_mle_receive_filter_set(mle_service_filter_cb *response_filter_cb);
#endif //NET_TEST_API_H_

View File

@ -274,6 +274,19 @@ int thread_test_increment_key_sequence_counter(int8_t interface_id);
*/
int thread_test_key_sequence_counter_update(int8_t interface_id, uint32_t thrKeySequenceCounter);
/**
* \brief Resets cached values from stack
*
Resets link configuration from cache and from NVM.
*
*
* \param interface_id Network Interface
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_stack_cache_reset(int8_t interface_id);
/**
* \brief Set new Thread key rotation value
*

View File

@ -758,7 +758,7 @@ static int mle_router_accept_request_build(protocol_interface_info_entry_t *cur,
static void protocol_6lowpan_link_reject_handler(protocol_interface_info_entry_t *cur, uint8_t *ll64)
{
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, 0, ll64, false);
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, 0, ll64, false, NULL);
tr_debug("MLE link reject");
if (entry_temp) {
mle_class_remove_entry(cur->id, entry_temp);
@ -1081,7 +1081,7 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
mle_6lowpan_data->link_req_token_bucket--;
} else {
//Update only old information based on link request
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
mle_neigh_time_and_mode_update(entry_temp,mle_msg->data_ptr, mle_msg->data_length);
mle_neigh_entry_update_by_mle_tlv_list(interface_id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
@ -1118,12 +1118,12 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
tr_debug("Accept & Request");
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (!entry_temp) {
// If there is space for neighbors try to allocate new entry
if (mle_6lowpan_neighbor_limit_check(interface_id, mle_msg, true)) {
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, true);
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, true, NULL);
}
}
@ -1185,7 +1185,7 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
mode = *t_ptr;
}
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (!entry_temp) {
if ((mode & MLE_DEV_MASK) == MLE_FFD_DEV) {
// If there is space for neighbors synchronizes to new router
@ -2787,7 +2787,7 @@ bool lowpan_neighbour_data_clean(int8_t interface_id, const uint8_t *link_local_
{
bool return_value = false;
#ifndef NO_MLE
mle_neigh_table_entry_t * neigh_entry = mle_class_get_entry_by_ll64(interface_id, 0, link_local_address, false);
mle_neigh_table_entry_t * neigh_entry = mle_class_get_entry_by_ll64(interface_id, 0, link_local_address, false, NULL);
if (neigh_entry) {
//Remove entry
if (neigh_entry->priorityFlag) {

View File

@ -87,7 +87,10 @@ static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur)
#endif
}
}
uint16_t pan_id = cur->mac_parameters->pan_id;
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
pana_reset_values(cur->mac_parameters->pan_id);
}
if (cur->interface_mode == INTERFACE_UP) {
if (cur->mac_api) {
mlme_reset_t reset;
@ -105,9 +108,6 @@ static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur)
reassembly_interface_reset(cur->id);
icmp_nd_routers_init();
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
pana_reset_values(pan_id);
}
if (cur->pana_sec_info_temp) {
ns_dyn_mem_free(cur->pana_sec_info_temp);

View File

@ -433,8 +433,9 @@ void mac_helper_coordinator_address_set(protocol_interface_info_entry_t *interfa
if (adr_type == ADDR_802_15_4_SHORT) {
memcpy(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, adr_ptr, 2);
interface->mac_parameters->mac_cordinator_info.cord_adr_mode = MAC_ADDR_MODE_16_BIT;
uint16_t short_addr = common_read_16_bit(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address);
set_req.attr = macCoordShortAddress;
set_req.value_pointer = &interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address;
set_req.value_pointer = &short_addr;
set_req.value_size = 2;
} else if (adr_type == ADDR_802_15_4_LONG) {
memcpy(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, adr_ptr, 8);
@ -767,8 +768,10 @@ static uint8_t mac_helper_header_security_aux_header_length(uint8_t keyIdmode) {
switch (keyIdmode) {
case MAC_KEY_ID_MODE_SRC8_IDX:
header_length += 4; //64-bit key source first part
/* fall through */
case MAC_KEY_ID_MODE_SRC4_IDX:
header_length += 4; //32-bit key source inline
/* fall through */
case MAC_KEY_ID_MODE_IDX:
header_length += 1;
break;
@ -830,13 +833,13 @@ void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index)
mac_api->mlme_req(mac_api,MLME_SET , &set_req);
}
void mac_helper_devicetable_set(mle_neigh_table_entry_t *entry_temp, protocol_interface_info_entry_t *cur, uint32_t frame_counter, uint8_t keyID)
void mac_helper_devicetable_set(mle_neigh_table_entry_t *entry_temp, protocol_interface_info_entry_t *cur, uint32_t frame_counter, uint8_t keyID, bool force_set)
{
if (!cur->mac_api) {
return;
}
if (cur->mac_parameters->SecurityEnabled && cur->mac_parameters->mac_default_key_index != keyID) {
if (!force_set && cur->mac_parameters->SecurityEnabled && cur->mac_parameters->mac_default_key_index != keyID) {
tr_debug("Do not set counter by index %u != %u", cur->mac_parameters->mac_default_key_index, keyID);
return;
}

View File

@ -110,7 +110,7 @@ int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr);
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index);
void mac_helper_devicetable_set(struct mle_neigh_table_entry_t *entry_temp, struct protocol_interface_info_entry *cur, uint32_t frame_counter, uint8_t keyID);
void mac_helper_devicetable_set(struct mle_neigh_table_entry_t *entry_temp, struct protocol_interface_info_entry *cur, uint32_t frame_counter, uint8_t keyID, bool force_set);
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);

View File

@ -252,6 +252,8 @@ int mac_pairwise_key_interface_unregister(int8_t interface_id)
int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const uint8_t eui64[static 8], const uint8_t key[static 16])
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
bool new_entry_created;
if (!interface || !interface->mac_api) {
return -1;
}
@ -264,7 +266,7 @@ int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const ui
}
//Allocate mle entry
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true);
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true, &new_entry_created);
if (!mle_entry) {
return -1;
}
@ -282,7 +284,7 @@ int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const ui
}
//Set device descriptor
mac_helper_devicetable_set(mle_entry, interface, 0, interface->mac_parameters->mac_default_key_index);
mac_helper_devicetable_set(mle_entry, interface, 0, interface->mac_parameters->mac_default_key_index, new_entry_created);
//set key descriptor
if (mac_helper_security_pairwisekey_set(interface, key, eui64, key_desc->key_decriptor_attribute) != 0) {
@ -308,7 +310,7 @@ int mac_pairwise_key_del(int8_t interface_id, const uint8_t eui64[static 8])
return -1;
}
//Get from mle
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true);
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true, NULL);
if (!mle_entry) {
return -1;
}

View File

@ -738,7 +738,7 @@ static bool thread_bbr_activated(thread_bbr_t *this, uint32_t seconds)
return true;
}
// We will try to become router. This is done only in 120 seconds intervals if failed
thread_router_bootstrap_router_id_request(cur, 0);
thread_router_bootstrap_router_id_request(cur, THREAD_BBR_ROUTER_ID_REQUEST_STATUS);
this->router_upgrade_delay_timer = 120;
return false;
}
@ -755,8 +755,8 @@ bool thread_bbr_routing_enabled(protocol_interface_info_entry_t *cur)
void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
{
(void) cur;
thread_mdns_network_data_update_notify();
thread_extension_bbr_route_update(cur);
}
#endif /* HAVE_THREAD_BORDER_ROUTER*/

View File

@ -63,6 +63,7 @@
#include "6LoWPAN/Thread/thread_network_synch.h"
#include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_extension.h"
#include "6LoWPAN/Thread/thread_extension_bbr.h"
#include "6LoWPAN/Thread/thread_management_client.h"
#include "6LoWPAN/Thread/thread_address_registration_client.h"
#include "6LoWPAN/Thread/thread_joiner_application.h"
@ -112,7 +113,6 @@ static void thread_bootsrap_network_discovery_failure(int8_t interface_id);
static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur);
static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info);
static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64);
@ -134,37 +134,6 @@ static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t
thread_reset_neighbour_info(cur_interface, cur);
}
static bool thread_child_keep_alive_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
{
uint8_t mac64[8];
uint8_t *ll64_ptr = mle_service_get_msg_destination_address_pointer(msgId);
memcpy(mac64, ll64_ptr + 8, 8);
mac64[0] ^= 2;
mle_neigh_table_entry_t *neig_info = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG);
if (!neig_info) {
return false;//Why entry is removed before timeout??
}
if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) {
return false;
}
if (usedAllRetries) {
//GET entry
mle_class_remove_entry(interface_id, neig_info);
return false;
}
return true;
}
int8_t thread_mle_class_init(int8_t interface_id)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
@ -182,7 +151,7 @@ int8_t thread_mle_class_init(int8_t interface_id)
return -1;
}
if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_child_keep_alive, &thread_interface_is_active) != 0) {
if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_host_bootstrap_child_update, &thread_interface_is_active) != 0) {
return -1;
}
@ -231,68 +200,6 @@ uint8_t thread_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur)
return mle_mode;
}
static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64)
{
mle_message_timeout_params_t timeout;
uint8_t ll64[16];
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
uint32_t keySequence;
uint16_t bufId;
uint8_t mode;
if (!cur) {
return -1;
}
if (!thread_info(cur)) {
return -1;
}
//routers do not send keep alive
if (thread_i_am_router(cur)){
return -1;
}
tr_debug("Child Keep Alive");
bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false,MLE_COMMAND_CHILD_UPDATE_REQUEST);
if (bufId == 0) {
return -1;
}
thread_management_get_current_keysequence(cur->id, &keySequence);
mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
mode = thread_mode_get_by_interface_ptr(cur);
uint8_t *ptr = mle_service_get_data_pointer(bufId);
ptr = mle_general_write_source_address(ptr, cur);
ptr = mle_tlv_write_mode(ptr, mode);
ptr = thread_leader_data_tlv_write(ptr, cur);
//Set Addresss TLV
if ((mode & MLE_FFD_DEV) == 0) {
ptr = thread_address_registration_tlv_write(ptr, cur);
}
memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(&ll64[8], mac64, 8);
ll64[8] ^= 2;
if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
tr_debug("Buffer overflow at message write");
}
timeout.retrans_max = 3;
timeout.timeout_init = 1;
timeout.timeout_max = 4;
timeout.delay = MLE_NO_DELAY;
//SET Destination address
mle_service_set_msg_destination_address(bufId, ll64);
//Set Callback
mle_service_set_packet_callback(bufId, thread_child_keep_alive_callback);
mle_service_set_msg_timeout_parameters(bufId, &timeout);
mle_service_send_message(bufId);
return 0;
}
/**
* Return lower (worse) of the two margins.
*/
@ -419,17 +326,24 @@ int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uin
tr_debug("Dropping advertisement from old partition without sequence number increase");
return -2;
}
if (heard_partition_routers == 0 && active_routers == 1) {
//heard a REED and I am in a singleton partition so merge
tr_debug("Heard a REED and I am a singleton - merge");
return 2;
}
/*Rule 0: If we are going to form Higher partition than heard we dont try to attach to lower ones
*/
if (thread_extension_enabled(cur) &&
thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER &&
heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) {
return -2;
thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
if (heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) {
tr_debug("Heard a lower weight partition");
return -2;
}
if (heard_partition_leader_data->weighting > thread_info(cur)->partition_weighting) {
return 2;
}
}
if ((heard_partition_routers == 0 && active_routers == 1) && thread_am_router(cur)) {
//heard a REED and I am a lonely router in a singleton partition, so merge
tr_debug("Heard a REED and I am a singleton - merge");
return 2;
}
//Rule 1: A non-singleton Thread Network Partition always has higher priority than a singleton Thread Network Partition
@ -768,6 +682,8 @@ int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, l
thread_extension_activate(cur);
thread_extension_bbr_route_update(cur);
blacklist_clear();
blacklist_params_set(
@ -1014,6 +930,7 @@ static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE;
//SET Sleepy Host To RX on Idle mode for bootsrap
nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
cur->thread_info->childUpdateReqTimer = 0.8 * cur->thread_info->host_link_timeout;
} else {
tr_debug("Set End node Mode");
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
@ -1134,7 +1051,9 @@ void thread_tasklet(arm_event_s *event)
case THREAD_CHILD_UPDATE:
tr_debug_extra("Thread SM THREAD_CHILD_UPDATE");
thread_bootstrap_child_update(cur);
if (thread_info(cur)->thread_endnode_parent) {
thread_host_bootstrap_child_update(cur->id, cur->thread_info->thread_endnode_parent->mac64);
}
break;
case THREAD_ANNOUNCE_ACTIVE: {
tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE");
@ -1245,14 +1164,14 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur)
mac_data_poll_protocol_poll_mode_decrement(cur);
}
void thread_clean_all_routers_from_neighbor_list(int8_t interface_id)
void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur)
{
mle_neigh_table_list_t *neig_list = mle_class_active_list_get(interface_id);
/* Init Double linked Routing Table */
ns_list_foreach_safe(mle_neigh_table_entry_t, cur, neig_list) {
if (thread_is_router_addr(cur->short_adr)) {
tr_debug("Free Router %x", cur->short_adr);
mle_class_remove_entry(interface_id, cur);
mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id);
ns_list_foreach_safe(mle_neigh_table_entry_t, cur_entry, neig_list) {
if (!thread_addr_is_equal_or_child(cur->thread_info->routerShortAddress, cur_entry->short_adr)) {
tr_debug("Free ID %x", cur_entry->short_adr);
mle_class_remove_entry(cur->id, cur_entry);
}
}
}
@ -1751,6 +1670,23 @@ bool thread_network_data_timeout(int8_t interface_id, uint16_t msgId, bool usedA
return true;
}
if(cur->thread_info->leader_synced) {
if(usedAllRetries) {
// could not learn network data from neighbour, everyone must reregister
cur->thread_info->leader_synced = false;
thread_leader_service_network_data_changed(cur,true,true);
return false;
} else {
tr_debug("retrying as leader data not yet synced");
return true;
}
}
// if REED fails to get updated network data, it reattaches
if (thread_info(cur)->networkDataRequested && !thread_attach_active_router(cur) && usedAllRetries) {
thread_bootstrap_reset_restart(interface_id);
}
thread_info(cur)->networkDataRequested = false;
mac_data_poll_protocol_poll_mode_decrement(cur);
return false;
@ -1876,7 +1812,7 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[
}
}
static bool thread_dhcpv6_address_valid(uint8_t *prefixPtr, if_address_list_t *list)
bool thread_dhcpv6_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list)
{
bool addressReady = false;
ns_list_foreach(if_address_entry_t, entry, list) {
@ -2333,21 +2269,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
void thread_bootstrap_child_update_trig(protocol_interface_info_entry_t *cur)
{
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
if (cur->thread_info->thread_endnode_parent == NULL) {
return;
}
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
//Set Pending if earlier proces is already started
cur->thread_info->thread_endnode_parent->childUpdatePending = true;
return;
}
//Trig event
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && cur->thread_info->thread_endnode_parent) {
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
}
}
@ -2584,8 +2506,8 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur,
memcpy(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6);
common_write_16_bit(genericService.routerID, &addr[14]);
thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
tr_debug("Delete DHCPv6 given address");
thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
}
}
@ -2812,7 +2734,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
bool validToLearnRoutes, validToLearOnMeshRoute;
thread_network_server_data_entry_t *weHostService = NULL;
uint16_t routerId;
tr_debug("Network Data:");
tr_debug("Network Data process:");
routerId = cur->mac_parameters->mac_short_address;
thread_network_data_cache_entry_t *networkData;
networkData = &cur->thread_info->networkDataStorage;
@ -2875,14 +2797,14 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
}
}
if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
/* Do not allow multiple DHCP solicits from one prefix => delete previous */
thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix);
if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) {
tr_debug("GP Address Requested");
}
}
} else {
/* All end device types perform RLOC16 -> 0xfffe
replacement if stable network data was requested. */
@ -2895,7 +2817,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
}
if (curBorderRouter->P_preferred) {
if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT);
}
}

View File

@ -106,7 +106,7 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg,
int thread_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mle_neigh_table_entry_t *child);
void thread_bootstrap_ready(struct protocol_interface_info_entry *cur);
int thread_bootstrap_reset(struct protocol_interface_info_entry *cur);
void thread_clean_all_routers_from_neighbor_list(int8_t interface_id);
void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur);
bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address);
bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mle_neigh_table_entry_t *entry_temp);
void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur);

View File

@ -884,9 +884,20 @@ int thread_border_router_publish(int8_t interface_id)
tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16);
if (cur->thread_info->localServerDataBase.publish_active) {
cur->thread_info->localServerDataBase.publish_pending = true;
tr_debug("Activate pending status for publish");
return 0;
if (rloc16 != cur->thread_info->localServerDataBase.registered_rloc16) {
/*
* Device short address has changed, cancel previous a/sd and a/as requests
* and start resubmit timer
* */
tr_debug("address changed, kill pending reuqests");
thread_management_client_pending_coap_request_kill(cur->id);
thread_border_router_resubmit_timer_set(interface_id, 5);
return 0;
} else {
cur->thread_info->localServerDataBase.publish_pending = true;
tr_debug("Activate pending status for publish");
return 0;
}
}
//Allocate Memory for Data

View File

@ -233,8 +233,8 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur)
tr_debug("SET thread Idle");
//stop polling
mac_data_poll_disable(cur);
//Clean routers from mle table
thread_clean_all_routers_from_neighbor_list(cur->id);
//Clean mle table
thread_neighbor_list_clean(cur);
// store frame counters
if (cur->thread_info) {
thread_nvm_fast_data_t fast_data;
@ -249,6 +249,7 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur)
thread_joiner_application_configuration_nvm_save(cur->id);
mac_pairwise_key_flush_list(cur->id);
thread_discovery_reset(cur->id);
thread_leader_mleid_rloc_map_to_nvm_write(cur);
thread_bootstrap_stop(cur);
mle_service_interface_unregister(cur->id);
thread_management_server_delete(cur->id);
@ -524,6 +525,7 @@ thread_leader_info_t *thread_allocate_and_init_leader_private_data(void)
thread_leader_info_t *leader_info = ns_dyn_mem_alloc(sizeof(thread_leader_info_t));
if (leader_info) {
leader_info->leader_id_seq_timer = ID_SEQUENCE_PERIOD;
leader_info->leader_nvm_sync_timer = 0;
}
return leader_info;
}
@ -717,6 +719,7 @@ void thread_child_id_request_info_init(thread_pending_child_id_req_t *child_info
thread_pending_child_id_req_t *thread_child_id_request_allocate(void)
{
thread_pending_child_id_req_t *req = ns_dyn_mem_alloc(sizeof(thread_pending_child_id_req_t));
memset(req->eiid, 0 , 8);
thread_child_id_request_info_init(req);
return req;
}
@ -880,7 +883,6 @@ static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur,
if (cur->thread_info->childUpdateReqTimer == -1) {
return;
}
if (cur->thread_info->childUpdateReqTimer > seconds) {
cur->thread_info->childUpdateReqTimer -= seconds;
} else {
@ -1712,7 +1714,8 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_
// Maximum length of address registrations
continue;
}
if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL) {
if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL
&& !thread_addr_is_mesh_local_16(e->address, cur))) {
ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address);
if (ctx) {
//Write TLV to list
@ -1725,7 +1728,6 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_
memcpy(ptr, e->address, 16);
ptr += 16;
*address_len_ptr += 17;
}
}
}
@ -1838,7 +1840,7 @@ static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failure
}
if (accumulated_failures >= THREAD_MAC_TRANSMISSIONS*THREAD_FAILED_CHILD_TRANSMISSIONS) {
thread_reset_neighbour_info(cur, neighbor);
mle_class_remove_entry(cur->id, neighbor);
}
}
@ -1848,8 +1850,8 @@ void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mle_neigh
thread_parent_info_t *thread_endnode_parent = thread_info(cur)->thread_endnode_parent;
if (!thread_i_am_router(cur) && thread_endnode_parent && thread_endnode_parent->shortAddress == neighbour->short_adr) {
tr_warn("End device lost Parent!\n");
if(cur->nwk_bootstrap_state != ER_CHILD_ID_REQ) {
tr_warn("End device lost parent, reset!\n");
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
}
}

View File

@ -48,6 +48,8 @@
*/
#define ROUTER_ID_REUSE_DELAY 100 //Seconds
#define LEADER_NVM_SYNC_DELAY 30 // Leader router ids write delay to NVM
#define ROUTER_ID_INFINITY_DELAY 90 //Seconds
#define NETWORK_ID_TIMEOUT 120 //seconds
@ -145,6 +147,7 @@ typedef struct thread_leader_info_s {
uint8_t leader_id_seq_timer;
uint8_t master_router_id_mask[8];
uint8_t maskSeq;
uint8_t leader_nvm_sync_timer;
} thread_leader_info_t;
typedef struct thread_leader_data_s {
@ -174,7 +177,6 @@ typedef struct thread_parent_info_s {
uint8_t pathCostToLeader;
bool childUpdatePending: 1;
bool childUpdateProcessActive: 1;
bool childUpdateProcessStatus: 1;
} thread_parent_info_t;
@ -287,8 +289,10 @@ typedef struct thread_info_s {
uint16_t native_commissioner_port;
uint16_t routerShortAddress;
uint16_t reedJitterTimer;
uint16_t reedMergeAdvTimer;
uint16_t routerIdReqCoapID; // COAP msg id of RouterID request
int16_t childUpdateReqTimer;
uint16_t childUpdateReqMsgId;
uint16_t proactive_an_timer;
//uint8_t lastValidRouteMask[8];
int8_t interface_id; //Thread Interface ID

View File

@ -31,6 +31,10 @@
#ifndef THREAD_CONFIG_H_
#define THREAD_CONFIG_H_
/**
* Thread stack configuration values. All constants that are specified in Thread specification can be found from thread_constants.h
*/
#include "thread_constants.h"
/**
@ -307,6 +311,21 @@
*/
#define THREAD_PROACTIVE_AN_SEND_DELAY 2
/*
* Parent response wait time (in 100ms) when "R" bit is set in scan mask TLV (rounded up from 0.75 seconds)
*/
#define THREAD_PARENT_REQ_SCANMASK_R_TIMEOUT 9
/*
* Parent response wait time (in 100ms) when both "R" and "E" bit is set in scan mask TLV (rounded up from 1.25 seconds)
*/
#define THREAD_PARENT_REQ_SCANMASK_RE_TIMEOUT 15
/*
* When BBR is started, router address is requested from leader with following status
*/
#define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST
/**
* Build time flag to enable THCI special traces for test harness purposes
*/

View File

@ -31,7 +31,7 @@
#define THREAD_CONSTANTS_H_
/**
* Constants defined in Thread specifications
* Constants defined in Thread specifications. All configured values are defined in thread_config.h
*/
/**
@ -164,7 +164,7 @@
#define THREAD_ENTERPRISE_NUMBER 44970
#define THREAD_ADDR_REG_TIMEOUT_BASE 300
#define THREAD_ADDR_REG_RETRY_INTERVAL 300
#define THREAD_PROACTIVE_AN_INTERVAL 3600
// Router defines
@ -174,6 +174,10 @@
#define MIN_DOWNGRADE_NEIGHBORS 7
#define THREAD_REED_ADVERTISEMENT_DELAY 5000
// Interval after which REED can send an advertisement to help others merge to higher partition.
// This is not related to default REED advertisements.
#define THREAD_REED_MERGE_ADVERTISEMENT_INTERVAL 120
/** Default Threshold for router Selection */
#define ROUTER_DOWNGRADE_THRESHOLD 23 // Define downGrade Threshold when active router is higher than this
#define ROUTER_UPGRADE_THRESHOLD 16 // Define upgrade Threshold fort REED when Active Router Count is smaller than this upgrade is possible

View File

@ -135,6 +135,13 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
tr_error("Sol Not include all Options");
goto error_exit;
}
if (libdhcpv6_nonTemporal_entry_get_by_iaid(dhcp_ia_non_temporal_params.iaId) != srv_data_ptr) {
/* Validate server data availability */
tr_error("Valid instance not found");
goto error_exit;
}
if (srv_data_ptr->IAID != dhcp_ia_non_temporal_params.iaId) {
tr_error("Wrong IAID");
goto error_exit;
@ -181,7 +188,9 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
tr_error("Invalid parameters");
return -1;
}
srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr);
payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0);
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
@ -207,6 +216,7 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb);
return srv_data_ptr->transActionId ? 0 : -1;
}
void thread_dhcp_client_global_address_renew(int8_t interface)
{
// only prepared for changes in thread specifications
@ -219,15 +229,23 @@ void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_add
protocol_interface_info_entry_t *cur;
dhcpv6_client_server_data_t *srv_data_ptr;
(void) dhcp_addr;
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
cur = protocol_stack_interface_info_get_by_id(interface);
if (cur == NULL || srv_data_ptr == NULL) {
tr_error("Not valid prefix");
return;
}
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
do {
if (cur == NULL || srv_data_ptr == NULL) {
return;
}
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
tr_debug("Deleting address: %s", trace_ipv6(srv_data_ptr->iaNontemporalAddress.addressPrefix));
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
} while (srv_data_ptr);
return;
}
@ -306,7 +324,7 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
if (address_entry == NULL) {
tr_error("Address add failed");
return ;
return;
}
if (renewTimer) {
// translate seconds to 100ms ticks
@ -316,7 +334,6 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
renewTimer = 0xfffffffe;
}
}
tr_debug("Added new address");
address_entry->state_timer = renewTimer;
address_entry->cb = thread_dhcpv6_renew;
}

View File

@ -817,6 +817,12 @@ static void thread_discovery_request_msg_handler(thread_discovery_class_t * disc
}
tr_debug("Thread discovery request message RX");
// Check if we have room for new neighbor
if (mle_class_free_entry_count_get(discovery_class->interface_id) < 1) {
tr_debug("MLE table full, skip request");
return;
}
//validate message
mle_tlv_info_t discovery_tlv;
//Parse Message

View File

@ -38,15 +38,30 @@
extern "C" {
#endif
#if defined(HAVE_THREAD_V2) && defined(HAVE_THREAD_BORDER_ROUTER)
int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_id);
void thread_extension_bbr_delete(int8_t interface_id);
bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc);
void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds);
int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port);
void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur);
#else
#define thread_extension_bbr_init(interface_id, backbone_interface_id)
#define thread_extension_bbr_delete(interface_id)
#define thread_extension_bbr_nd_query_process(cur, target_addr) false
#define thread_extension_bbr_nd_query_process(cur, target_addr, rloc) false
#define thread_extension_bbr_seconds_timer(interface_id, seconds)
#define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay)
#define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1)
#define thread_extension_bbr_route_update(cur)
#endif
#ifdef __cplusplus
}
#endif
#endif /* THREAD_EXTENSION_BBR_H_ */
#endif //HAVE_THREAD_BORDER_ROUTER && HAVE_THREAD_V2

View File

@ -88,7 +88,6 @@ static int thread_parent_request_build(protocol_interface_info_entry_t *cur);
static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur);
static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader);
static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr);
static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur);
@ -122,18 +121,17 @@ static void thread_merge_prepare(protocol_interface_info_entry_t *cur)
{
thread_clean_old_16_bit_address_based_addresses(cur);
mpl_clear_realm_scope_seeds(cur);
ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
thread_routing_deactivate(&cur->thread_info->routing);
thread_routing_init(&cur->thread_info->routing);
cur->nwk_mode = ARM_NWK_GP_IP_MODE;
thread_old_partition_data_purge(cur);
thread_network_data_clean(cur);
cur->nwk_mode = ARM_NWK_GP_IP_MODE;
}
//This function is for Thread Parent scan callback
static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
{
protocol_interface_info_entry_t *cur;
bool new_entry_created;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
@ -159,7 +157,7 @@ static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgI
memcpy(&ll64[8], parent->mac64 , 8);
ll64[8] ^= 2;
entry_temp = mle_class_get_entry_by_ll64(interface_id, parent->linkMarginToParent,ll64, true);
entry_temp = mle_class_get_entry_by_ll64(interface_id, parent->linkMarginToParent,ll64, true, &new_entry_created);
if (entry_temp == NULL) {
return false;
}
@ -172,7 +170,7 @@ static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgI
thread_management_key_sets_calc(cur, linkConfiguration, cur->thread_info->thread_attach_scanned_parent->keySequence);
thread_calculate_key_guard_timer(cur, linkConfiguration, true);
mac_helper_devicetable_set(entry_temp, cur, parent->linLayerFrameCounter, mac_helper_default_key_index_get(cur));
mac_helper_devicetable_set(entry_temp, cur, parent->linLayerFrameCounter, mac_helper_default_key_index_get(cur), new_entry_created);
mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
@ -229,13 +227,20 @@ static int thread_parent_request_build(protocol_interface_info_entry_t *cur)
return -1;
}
timeout.retrans_max = THREAD_PARENT_REQUEST_MAX_RETRY_CNT;
timeout.timeout_init = THREAD_PARENT_REQ_SCANMASK_R_TIMEOUT;
timeout.timeout_max = THREAD_PARENT_REQ_SCANMASK_RE_TIMEOUT;
timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH ||
cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY ||
cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED ||
cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
// When doing re-attach End devices are immediately accepted as parents
scanMask |= 0x40;
timeout.timeout_init = THREAD_PARENT_REQ_SCANMASK_RE_TIMEOUT;
}
thread_management_get_current_keysequence(cur->id, &keySequence);
mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
@ -258,11 +263,9 @@ static int thread_parent_request_build(protocol_interface_info_entry_t *cur)
if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
tr_debug("Buffer overflow at message write");
}
timeout.retrans_max = THREAD_PARENT_REQUEST_MAX_RETRY_CNT;
timeout.timeout_init = 1;
timeout.timeout_max = 2;
timeout.delay = MLE_NO_DELAY;
cur->nwk_nd_re_scan_count = 1;
mle_service_set_packet_callback(buf_id, thread_parent_discover_timeout_cb);
if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) {
mle_service_interface_receiver_handler_update(cur->id, thread_mle_parent_discover_receive_cb);
@ -270,7 +273,7 @@ static int thread_parent_request_build(protocol_interface_info_entry_t *cur)
mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
}
mle_service_set_msg_timeout_parameters(buf_id, &timeout);
mle_service_set_msg_timeout_parameters_fast(buf_id, &timeout);
mle_service_send_message(buf_id);
return 0;
}
@ -295,6 +298,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
uint32_t llFrameCounter;
thread_leader_data_t leaderData;
mle_neigh_table_entry_t *entry_temp;
bool new_entry_created;
tr_debug("Validate Link Synch Response");
//Check First Status
@ -325,7 +329,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
}
//Update parent link information
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, src_address, true);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, src_address, true, &new_entry_created);
if (!entry_temp) {
tr_debug("Neighbor allocate fail");
@ -343,7 +347,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, shortAddress);
mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, securityHeader->KeyIndex);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, securityHeader->KeyIndex, new_entry_created);
thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
thread_bootstrap_update_ml16_address(cur, address16);
@ -394,7 +398,7 @@ static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *ml
messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
@ -472,7 +476,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
return;
}
tr_debug("Thread MLE Parent request response Handler");
tr_debug("MLE Parent response handler");
//State machine What packet should accept in this case
switch (mle_msg->message_type) {
case MLE_COMMAND_PARENT_RESPONSE: {
@ -497,7 +501,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
@ -748,11 +752,12 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
return;
}
tr_debug("Thread MLE Child request response Handler");
tr_debug("Thread MLE Child ID response handler");
switch (mle_msg->message_type) {
case MLE_COMMAND_CHILD_ID_RESPONSE: {
uint8_t src_mac64[8];
uint8_t shortAddress[2];
uint16_t childId;
mle_tlv_info_t routeTlv, addressRegisteredTlv, networkDataTlv;
@ -760,22 +765,32 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
uint64_t pending_timestamp = 0;
uint64_t active_timestamp;
thread_scanned_parent_t *scan_result = thread_info(cur)->thread_attach_scanned_parent;
bool new_entry_created;
tr_info("Received Child ID Response");
tr_info("Recv Child ID Response");
// Validate that response is coming from the scanned parent candidate
memcpy(src_mac64, (mle_msg->packet_src_address + 8), 8);
src_mac64[0] ^= 2;
if (memcmp(src_mac64, scan_result->mac64, 8) != 0) {
tr_debug("Drop Child ID response from previous request");
return;
}
// Clear old data
if (cur->thread_info->releaseRouterId) {
thread_bootstrap_clear_neighbor_entries(cur);
cur->thread_info->localServerDataBase.release_old_address = true;
}
thread_clean_all_routers_from_neighbor_list(cur->id);
cur->thread_info->localServerDataBase.release_old_address = true;
thread_neighbor_list_clean(cur);
thread_leader_service_stop(interface_id);
thread_leader_service_leader_data_free(cur->thread_info);
thread_merge_prepare(cur);
// Create entry for new parent
entry_temp = mle_class_get_entry_by_ll64(cur->id, thread_compute_link_margin(mle_msg->dbm), mle_msg->packet_src_address, true);
entry_temp = mle_class_get_entry_by_ll64(cur->id, thread_compute_link_margin(mle_msg->dbm), mle_msg->packet_src_address, true, &new_entry_created);
if (entry_temp == NULL) {
// todo: what to do here?
return;
@ -832,7 +847,14 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, shortAddress);
mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout);
mac_helper_devicetable_set(entry_temp, cur, scan_result->linLayerFrameCounter, security_headers->KeyIndex);
if (scan_result->security_key_index != security_headers->KeyIndex) {
// KeyIndex has been changed between parent_response and child_id_response, reset link layer frame counter
scan_result->linLayerFrameCounter = 0;
scan_result->security_key_index = security_headers->KeyIndex;
}
mac_helper_devicetable_set(entry_temp, cur, scan_result->linLayerFrameCounter, security_headers->KeyIndex, new_entry_created);
thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
@ -868,7 +890,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
break;
}
default:
tr_debug("Unsupported TLV %d", mle_msg->message_type);
tr_debug("Skip msg type %d", mle_msg->message_type);
break;
}
@ -927,9 +949,10 @@ void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
{
if (cur->thread_info->thread_endnode_parent) {
mle_neigh_table_entry_t *entry_temp;
bool new_entry_created;
// Add the parent to the MLE neighbor table
entry_temp = mle_class_get_entry_by_mac64(cur->id, 64, cur->thread_info->thread_endnode_parent->mac64, true);
entry_temp = mle_class_get_entry_by_mac64(cur->id, 64, cur->thread_info->thread_endnode_parent->mac64, true, &new_entry_created);
if (entry_temp) {
entry_temp->short_adr = cur->thread_info->thread_endnode_parent->shortAddress;
@ -941,7 +964,7 @@ void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
mle_entry_timeout_update(entry_temp, 20);
// Add the parent to the MAC table (for e.g. secured/fragmented Child Update Response)
mac_helper_devicetable_set(entry_temp, cur, 0, cur->mac_parameters->mac_default_key_index);
mac_helper_devicetable_set(entry_temp, cur, 0, cur->mac_parameters->mac_default_key_index, new_entry_created);
}
}
@ -975,7 +998,7 @@ static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, boo
cur->thread_info->thread_attach_scanned_parent->child_id_request_id = 0;
uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId);
tr_debug("Child ID Request timed out, address: %s", trace_ipv6(addr));
tr_debug("Child ID Request timed out: %s", trace_ipv6(addr));
blacklist_update(addr, false);
@ -999,8 +1022,9 @@ static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, boo
memcpy(&ll64[8], scanned_parent->mac64 , 8);
ll64[8] ^= 2;
entry_temp = mle_class_get_entry_by_ll64(cur->id, scanned_parent->linkMarginToParent, ll64, false);
if (entry_temp) {
entry_temp = mle_class_get_entry_by_ll64(cur->id, scanned_parent->linkMarginToParent, ll64, false, NULL);
if (entry_temp && !thread_check_is_this_my_parent(cur, entry_temp)) {
// remove scanned_parent entry only if it is not my parent
mle_class_remove_entry(cur->id, entry_temp);
}
}
@ -1017,36 +1041,19 @@ static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, boo
cur->thread_info->localServerDataBase.release_old_address = false;
cur->thread_info->releaseRouterId = false;
cur->thread_info->networkDataRequested = false;
cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
exit:
mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent);
cur->thread_info->thread_attach_scanned_parent = NULL;
return false;
}
static uint8_t *thread_single_address_registration_tlv_write(uint8_t *ptr, lowpan_context_t *ctx, uint8_t *addressPtr)
{
*ptr++ = MLE_TYPE_ADDRESS_REGISTRATION;
if (ctx) {
*ptr++ = 9;
//Write TLV to list
*ptr++ = (ctx->cid | 0x80);
memcpy(ptr, addressPtr + 8, 8);
ptr += 8;
} else {
*ptr++ = 17;
//Write TLV to list
*ptr++ = 0;
memcpy(ptr, addressPtr, 16);
ptr += 16;
}
return ptr;
}
static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur)
{
uint8_t *ptr, *address_ptr;
@ -1069,8 +1076,6 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t
thread_management_get_current_keysequence(cur->id, &keySequence);
mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
lowpan_context_t *ctx;
uint8_t ml64[16];
uint8_t request_tlv_list[3];
uint8_t macShort[2];
uint8_t reqTlvCnt;
@ -1088,15 +1093,10 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t
ptr = mle_tlv_write_response(ptr, scan_parent->challengeData, scan_parent->chal_len);
//Add ML-EID
memcpy(ml64, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8);
memcpy(&ml64[8], cur->iid_slaac, 8);
if ((mode & MLE_FFD_DEV) == 0) {
ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, ml64);
if (ctx) {
//Write TLV to list
ptr = thread_single_address_registration_tlv_write(ptr, ctx, ml64);
}
ptr = thread_address_registration_tlv_write(ptr, cur);
}
reqTlvCnt = 2;
request_tlv_list[0] = MLE_TYPE_NETWORK_DATA;
@ -1133,53 +1133,54 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t
static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
(void)msgId;
if (!cur || !cur->thread_info->thread_endnode_parent) {
return false;
}
tr_debug("Child Update CB");
if (cur->thread_info->thread_endnode_parent->childUpdateProcessStatus) {
//This process is ready
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
if (!cur->thread_info->thread_endnode_parent->childUpdatePending) {
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
//Disable Poll
mac_data_poll_protocol_poll_mode_decrement(cur);
tr_debug("Child Update ready");
} else {
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
tr_debug("Child Update Pending");
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
}
if (msgId != cur->thread_info->childUpdateReqMsgId) {
//Wrong message id
return false;
}
if (usedAllRerties) {
tr_debug("Child Update timed out");
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
mac_data_poll_protocol_poll_mode_decrement(cur);
thread_bootstrap_reset_restart(cur->id);
tr_debug("Restart attachment");
return false;
}
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
// we have not received response so re-send
return true;
}
return true;
return false;
}
int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
mle_message_timeout_params_t timeout;
uint8_t mode;
uint32_t keySequence;
if (!cur->thread_info->thread_endnode_parent) {
return -1;
}
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
//Set Pending if earlier process is already started
cur->thread_info->thread_endnode_parent->childUpdatePending = true;
return -1;
}
//Trig event
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
tr_debug("Child Update Request");
mode = thread_mode_get_by_interface_ptr(cur);
@ -1196,11 +1197,12 @@ int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(bufId);
memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(address_ptr + 8, cur->thread_info->thread_endnode_parent->mac64, 8);
memcpy(address_ptr + 8, mac64, 8);
address_ptr[8] ^= 2;
uint8_t *ptr = mle_service_get_data_pointer(bufId);
ptr = mle_tlv_write_mode(ptr, mode);
ptr = mle_general_write_source_address(ptr, cur);
ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
ptr = thread_leader_data_tlv_write(ptr, cur);
@ -1221,9 +1223,11 @@ int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
thread_end_device_mode_set(cur, false);
}
mac_data_poll_init_protocol_poll(cur);
cur->thread_info->childUpdateReqMsgId = bufId;
mle_service_set_packet_callback(bufId, thread_child_update_timeout_cb);
mle_service_set_msg_timeout_parameters(bufId, &timeout);
mle_service_send_message(bufId);
return 0;
}
int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge)

View File

@ -42,7 +42,7 @@ struct protocol_interface_info_entry;
struct mle_security_header;
void thread_network_attach_start(struct protocol_interface_info_entry *cur);
int8_t thread_bootstrap_child_update(struct protocol_interface_info_entry *cur);
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64);
int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge);
void thread_child_set_default_route(struct protocol_interface_info_entry *cur);

View File

@ -917,6 +917,15 @@ link_configuration_s *thread_joiner_application_get_config(int8_t interface_id)
return this->configuration_ptr;
}
uint8_t *thread_joiner_application_network_name_get(int8_t interface_id)
{
thread_joiner_t *this = thread_joiner_find(interface_id);
if (!this) {
return NULL;
}
return this->configuration_ptr->name;
}
static int thread_joiner_application_nvm_link_config_read(thread_joiner_t *this) {
// read config from NVM, in case of failure current settings are unchanged.

View File

@ -69,6 +69,7 @@ struct link_configuration *thread_joiner_application_get_config(int8_t interface
uint64_t thread_joiner_application_active_timestamp_get(int8_t interface_id);
uint8_t thread_joiner_application_security_policy_get(int8_t interface_id);
void thread_joiner_application_active_timestamp_set(int8_t interface_id, uint64_t timestamp);
uint8_t *thread_joiner_application_network_name_get(int8_t interface_id);
uint8_t *thread_joiner_application_active_config_tlv_list_get(uint8_t interface_id, uint16_t *length);
uint8_t *thread_joiner_application_active_config_params_get(uint8_t interface_id, uint16_t *length);

View File

@ -733,6 +733,32 @@ static void thread_leader_allocate_router_id_by_allocated_id(thread_leader_info_
info->thread_router_id_list[router_id].reUsePossible = false;
}
void thread_leader_mleid_rloc_map_populate(thread_nvm_mleid_rloc_map *mleid_rloc_map, thread_leader_info_t *leader_private_info)
{
for (uint8_t i = 0; i < 64; i++) {
if (bit_test(leader_private_info->master_router_id_mask, i)) {
memcpy(mleid_rloc_map->mleid_rloc_map[i].mle_id, leader_private_info->thread_router_id_list[i].eui64, 8);
}
}
}
int thread_leader_mleid_rloc_map_to_nvm_write(protocol_interface_info_entry_t *cur)
{
if (!cur->thread_info->leader_private_data) {
return -1;
}
thread_nvm_mleid_rloc_map *mleid_rloc_map = ns_dyn_mem_temporary_alloc(sizeof(thread_nvm_mleid_rloc_map));
if (!mleid_rloc_map) {
return -2;
}
memset(mleid_rloc_map, 0, sizeof(thread_nvm_mleid_rloc_map));
thread_leader_mleid_rloc_map_populate(mleid_rloc_map, cur->thread_info->leader_private_data);
thread_nvm_store_mleid_rloc_map_write(mleid_rloc_map);
ns_dyn_mem_free(mleid_rloc_map);
return 0;
}
static int thread_leader_service_router_id_allocate(const uint8_t *eui64, protocol_interface_info_entry_t *cur, thread_leader_service_router_id_resp_t *reponse)
{
int ret_val = -1;
@ -793,6 +819,8 @@ static int thread_leader_service_router_id_allocate(const uint8_t *eui64, protoc
if (!bit_test(leader_private_ptr->master_router_id_mask, id)) {
if (leader_private_ptr->thread_router_id_list[id].reUsePossible) {
allocated_id = id;
// new id allocated save to nvm after delay
leader_private_ptr->leader_nvm_sync_timer = LEADER_NVM_SYNC_DELAY;
break;
}
}
@ -847,6 +875,7 @@ static int thread_leader_service_router_id_deallocate(const uint8_t *eui64, prot
//Active ID
if (memcmp(eui64, leader_private_ptr->thread_router_id_list[i].eui64, 8) == 0) {
tr_debug("Release Router Id %d", i);
leader_private_ptr->leader_nvm_sync_timer = LEADER_NVM_SYNC_DELAY;
thread_leader_service_route_mask_bit_clear(leader_private_ptr, i);
leader_private_ptr->thread_router_id_list[i].reUsePossible = true;
leader_private_ptr->thread_router_id_list[i].validLifeTime = 0;
@ -1270,7 +1299,7 @@ static int thread_leader_service_leader_init(protocol_interface_info_entry_t *cu
thread_nd_service_delete(cur->id);
mpl_clear_realm_scope_seeds(cur);
ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
thread_clean_all_routers_from_neighbor_list(cur->id);
thread_neighbor_list_clean(cur);
cur->mesh_callbacks = NULL;
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
@ -1318,6 +1347,8 @@ static void thread_leader_service_interface_setup_activate(protocol_interface_in
//SET Router ID
thread_leader_allocate_router_id_by_allocated_id(private, routerId, cur->mac);
thread_old_partition_data_purge(cur);
// remove any existing rloc mapping in nvm
thread_nvm_store_mleid_rloc_map_remove();
cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
thread_bootstrap_update_ml16_address(cur, cur->thread_info->routerShortAddress);
thread_generate_ml64_address(cur);
@ -1483,6 +1514,7 @@ void thread_leader_service_timer(protocol_interface_info_entry_t *cur, uint32_t
thread_bootstrap_network_data_update(cur);
}
}
if (cur->thread_info->leader_private_data->leader_id_seq_timer) {
if (cur->thread_info->leader_private_data->leader_id_seq_timer > ticks) {
cur->thread_info->leader_private_data->leader_id_seq_timer -= ticks;
@ -1499,6 +1531,16 @@ void thread_leader_service_timer(protocol_interface_info_entry_t *cur, uint32_t
thread_leader_service_network_data_changed(cur, false, false);
}
if (cur->thread_info->leader_private_data->leader_nvm_sync_timer) {
if ((cur->thread_info->leader_private_data->leader_nvm_sync_timer) > ticks) {
cur->thread_info->leader_private_data->leader_nvm_sync_timer -= ticks;
}
else {
cur->thread_info->leader_private_data->leader_nvm_sync_timer = 0;
thread_leader_mleid_rloc_map_to_nvm_write(cur);
}
}
thread_leader_service_router_id_valid_lifetime_update(cur, ticks);
}
@ -1618,25 +1660,39 @@ int thread_leader_service_thread_partitition_restart(int8_t interface_id, mle_tl
}
//Learn network data, we remove own data from here it should be re given by application
//thread_management_network_data_register(cur->id, networkData.dataPtr, networkData.tlvLen, address16 );
thread_nvm_mleid_rloc_map *mleid_rloc_map = ns_dyn_mem_temporary_alloc(sizeof(thread_nvm_mleid_rloc_map));
if (!mleid_rloc_map) {
return -1;
}
if (thread_nvm_store_mleid_rloc_map_read(mleid_rloc_map) != THREAD_NVM_FILE_SUCCESS) {
memset(mleid_rloc_map, 0, sizeof(thread_nvm_mleid_rloc_map));
}
// initialize private data
thread_info(cur)->leader_private_data->maskSeq = *routing->dataPtr;
memcpy(thread_info(cur)->leader_private_data->master_router_id_mask,routing->dataPtr + 1,8);
memcpy(thread_info(cur)->leader_private_data->master_router_id_mask,routing->dataPtr + 1, 8);
for (int i = 0; i < 64; i++) {
memset(thread_info(cur)->leader_private_data->thread_router_id_list[i].eui64,0,8);
if (bit_test(thread_info(cur)->leader_private_data->master_router_id_mask, i)) {
//Active ID
thread_info(cur)->leader_private_data->thread_router_id_list[i].reUsePossible = false;
memcpy(thread_info(cur)->leader_private_data->thread_router_id_list[i].eui64, mleid_rloc_map->mleid_rloc_map[i].mle_id, 8);
} else {
// Free id
thread_info(cur)->leader_private_data->thread_router_id_list[i].reUsePossible = true;
// clear the mleid in both local router id list and nvm
memset(thread_info(cur)->leader_private_data->thread_router_id_list[i].eui64, 0, 8);
memset(mleid_rloc_map->mleid_rloc_map[i].mle_id, 0, 8);
}
thread_info(cur)->leader_private_data->thread_router_id_list[i].validLifeTime = 0xffffffff;
}
// write back updated map to store
thread_nvm_store_mleid_rloc_map_write(mleid_rloc_map);
ns_dyn_mem_free(mleid_rloc_map);
// Clear network data (if exists) and propagate new empty network data
thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage);
thread_network_data_base_init(&cur->thread_info->networkDataStorage);
// Update router sequence id to prevent network fragmentation in case of Leader was temporarily down
// and routers were not able to get new sequence id for NETWORK_ID_TIMEOUT duration.
thread_leader_service_update_id_set(cur);
return 0;
}

View File

@ -118,6 +118,8 @@ void thread_leader_service_network_data_changed(protocol_interface_info_entry_t
void thread_leader_service_timer(protocol_interface_info_entry_t *cur, uint32_t ticks);
int thread_leader_mleid_rloc_map_to_nvm_write(protocol_interface_info_entry_t *cur);
/** Get first child ID from network data based on parent ID
*
* \param thread_info
@ -161,6 +163,8 @@ void thread_leader_service_router_state_changed(thread_info_t *thread_info, uint
#define thread_leader_service_router_state_changed(thread_info, router_id, available, interface_id)
#define thread_leader_mleid_rloc_map_to_nvm_write(cur) (0)
#endif /*HAVE_THREAD_LEADER_SERVICE*/
#endif /* _THREAD_LEADER_SERVICE_H_ */

View File

@ -102,7 +102,7 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg,
case MLE_COMMAND_REJECT: {
mle_neigh_table_entry_t *entry_temp;
tr_warn("Reject Link");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
mle_class_remove_entry(cur->id, entry_temp);
}
@ -224,8 +224,6 @@ static bool thread_router_leader_data_process(protocol_interface_info_entry_t *c
// 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");
@ -239,27 +237,16 @@ static bool thread_router_leader_data_process(protocol_interface_info_entry_t *c
return true;
}
static bool thread_reed_partitions_merge(protocol_interface_info_entry_t *cur, uint16_t shortAddress, thread_leader_data_t heard_partition_leader_data)
static bool thread_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data)
{
if (thread_is_router_addr(shortAddress)) {
return false;
if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) {
return true;
}
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;
if (heard_partition_leader_data.weighting == thread_info(cur)->thread_leader_data->weighting &&
heard_partition_leader_data.partitionId < thread_info(cur)->thread_leader_data->partitionId) {
return true;
}
// can merge to a higher weighting/partition id
thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
return true;
return false;
}
static bool thread_router_advertiment_tlv_analyze(uint8_t *ptr, uint16_t data_length, thread_leader_data_t *leaderData, uint16_t *shortAddress, mle_tlv_info_t *routeTlv)
@ -315,12 +302,31 @@ static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_me
return;
}
static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address)
{
if ((thread_info(cur)->thread_leader_data->partitionId != leader_data->partitionId) ||
(thread_info(cur)->thread_leader_data->weighting != leader_data->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, leader_data, short_address)) {
tr_debug("Parent short address changed - re-attach");
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
return false;
}
return true;
}
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;
uint16_t shortAddress;
bool adv_from_my_partition;
bool my_parent;
// Check device mode & bootstrap state
if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) ||
@ -336,29 +342,27 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
}
// Get MLE entry
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
&& (thread_instance_id_matches(cur, &leaderData))) {
// Check if this is from my parent
my_parent = thread_check_is_this_my_parent(cur, entry_temp);
adv_from_my_partition = thread_instance_id_matches(cur, &leaderData);
if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) {
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;
}
if (entry_temp && !adv_from_my_partition && !my_parent ) {
// Remove MLE entry that are located in other partition and is not my parent
mle_class_remove_entry(cur->id, entry_temp);
entry_temp = NULL;
}
/* Check parent status */
if (!thread_attach_active_router(cur) && my_parent) {
if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) {
return;
}
}
@ -367,26 +371,31 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
// Process advertisement
if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
/* REED and FED */
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)) {
/* Check if advertisement is from same partition */
if (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId ) {
if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
// 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
/* Advertisement from higher / lower partition */
} else {
// Check if better partition is heard
if (thread_bootstrap_partition_process(cur, thread_get_router_count_from_route_tlv(&routeTlv), &leaderData, &routeTlv) > 0) {
tr_debug("Start Merge");
thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
return;
}
// REED advertisement to lower partition to help merge faster
if (thread_heard_lower_partition(cur,leaderData)) {
thread_router_bootstrap_reed_merge_advertisement(cur);
}
}
// process REED advertisement from higher partition
if (thread_reed_partitions_merge(cur, shortAddress, leaderData)) {
return;
}
/* ROUTER */
} else {
//Router
if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) {
return;
}
@ -409,14 +418,14 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
uint16_t messageId;
uint8_t linkMarginfronNeigh;
mle_neigh_table_entry_t *entry_temp;
bool createNew;
bool createNew, new_entry_created;
tr_info("MLE LINK ACCEPT");
messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
@ -435,7 +444,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
/* Call to determine whether or not we should create a new link */
createNew = thread_bootstrap_link_create_check(cur, shortAddress);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry_created);
if (!entry_temp) {
thread_link_reject_send(cur, mle_msg->packet_src_address);
@ -457,7 +466,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
// Set full data as REED needs full data and SED will not make links
entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry_created);
if (entry_temp->timeout_rx) {
mle_entry_timeout_refresh(entry_temp);
@ -551,7 +560,7 @@ static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle
return;
}
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ||
cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
@ -700,7 +709,7 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent
bool data_request_needed = false;
tr_debug("Child update request");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) ||
!entry_temp ||
@ -763,10 +772,15 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
uint8_t status;
bool leader_data_received;
if (cur->thread_info->thread_endnode_parent == NULL) {
return;
}
tr_debug("Child Update Response");
//mle_service_buffer_find
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);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
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)) {
@ -783,8 +797,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
return;
}
if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
&& (thread_instance_id_matches(cur, &leaderData))) {
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
} else {
tr_debug("Key ID Mode 2 not used; dropped.");
@ -796,12 +809,13 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
return;
}
timeout = cur->thread_info->host_link_timeout;
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);
@ -809,7 +823,22 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
if (leader_data_received) {
thread_save_leader_data(cur, &leaderData);
}
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
if (cur->thread_info->childUpdateReqTimer < 1) {
cur->thread_info->childUpdateReqTimer = 0.8 * timeout;
}
}
//This process is ready
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
if (cur->thread_info->thread_endnode_parent->childUpdatePending) {
tr_debug("Child Update Pending");
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
return;
}
mac_data_poll_protocol_poll_mode_decrement(cur);
}
#endif

View File

@ -209,7 +209,7 @@ static mle_neigh_table_entry_t *thread_nd_child_mleid_get(int8_t interface_id, u
return NULL;
}
static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t target_addr[static 16], uint16_t *addr_out, bool *proxy, uint32_t *last_transaction_time, uint8_t *mleid_ptr)
static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t target_addr[static 16], uint16_t *rloc, uint16_t *addr_out, bool *proxy, uint32_t *last_transaction_time, uint8_t *mleid_ptr)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
@ -260,8 +260,8 @@ static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t tar
can_route_of_mesh = true;
}
if (thread_extension_bbr_nd_query_process(cur,target_addr)) {
can_route_of_mesh = true;
if (thread_extension_bbr_nd_query_process(cur,target_addr, *rloc)){
return -1;
}
if (can_route_of_mesh) {

View File

@ -184,7 +184,7 @@ typedef struct thread_network_local_data_cache_entry_s {
thread_network_data_prefix_list_t prefix_list; /*!< Local parsed or generated service list */
thread_network_data_service_list_t service_list;
uint16_t registered_rloc16;/*!< Address used for latest registration */
bool release_old_address:1;/*!< true if release of old address is needed */
bool release_old_address:1;/*!< true if network data can be released from old address */
bool publish_active:1;/*!< true when publish is active */
bool publish_pending:1;/*!< true when publish attempt made during active publish */
} thread_network_local_data_cache_entry_t;

View File

@ -238,6 +238,7 @@ void thread_dynamic_storage_build_mle_table(int8_t interface_id)
tr_debug("Dynamic storage: building MLE table.");
thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
bool new_entry_created;
if (!storeEntry) {
storeEntry = thread_network_synch_create(interface_id);
@ -261,7 +262,7 @@ void thread_dynamic_storage_build_mle_table(int8_t interface_id)
}
uint8_t *mac64 = storeEntry->networ_dynamic_data_parameters.children[i].long_addr;
tr_debug("Child: %04x, %s", storeEntry->networ_dynamic_data_parameters.children[i].short_addr, trace_array(mac64, 8));
mle_neigh_table_entry_t *entry = mle_class_get_entry_by_mac64(interface_id, 64, mac64, true);
mle_neigh_table_entry_t *entry = mle_class_get_entry_by_mac64(interface_id, 64, mac64, true, &new_entry_created);
if (entry) {
entry->short_adr = storeEntry->networ_dynamic_data_parameters.children[i].short_addr;
entry->mle_frame_counter = storeEntry->networ_dynamic_data_parameters.children[i].mle_frame_counter;
@ -272,7 +273,7 @@ void thread_dynamic_storage_build_mle_table(int8_t interface_id)
if (cur && cur->mac_parameters) {
// Set MAC layer frame counter for the child
mac_helper_devicetable_set(entry, cur, storeEntry->networ_dynamic_data_parameters.children[i].mac_frame_counter, cur->mac_parameters->mac_default_key_index);
mac_helper_devicetable_set(entry, cur, storeEntry->networ_dynamic_data_parameters.children[i].mac_frame_counter, cur->mac_parameters->mac_default_key_index, new_entry_created);
}
}
}

View File

@ -52,6 +52,9 @@ const char *FAST_DATA_FILE = "f_d";
const char *LINK_INFO_FILE = "l_i";
#define LINK_INFO_DATA_VERSION 1
const char *LEADER_INFO_FILE = "ld_i";
#define LEADER_INFO_DATA_VERSION 1
typedef struct {
uint8_t mac[8];
uint16_t short_addr;
@ -88,6 +91,7 @@ static void thread_nvm_store_link_info_delayed_write(uint32_t seconds);
#define DEVICE_CONF_STRING_LEN (strlen(DEVICE_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1)
#define PENDING_CONF_STRING_LEN (strlen(THREAD_NVM_PENDING_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1)
#define LINK_INFO_STRING_LEN (strlen(LINK_INFO_FILE)+strlen(thread_nvm_store_get_root_path())+1)
#define LEADER_INFO_STRING_LEN (strlen(LEADER_INFO_FILE)+strlen(thread_nvm_store_get_root_path())+1)
thread_nvm_fast_data_t cached_fast_data;
@ -117,6 +121,65 @@ static int root_path_valid(void)
}
return 1;
}
int thread_nvm_store_mleid_rloc_map_write(thread_nvm_mleid_rloc_map *mleid_rloc_map)
{
char lc_data_path[LEADER_INFO_STRING_LEN];
if (!root_path_valid()) {
return THREAD_NVM_FILE_ROOT_PATH_INVALID;
}
thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE);
tr_debug("writing to store rloc mapping info");
return thread_nvm_store_write(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), LEADER_INFO_DATA_VERSION);
}
int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map)
{
char lc_data_path[LEADER_INFO_STRING_LEN];
uint32_t version;
if (NULL==mleid_rloc_map) {
return THREAD_NVM_FILE_PARAMETER_INVALID;
}
if (!root_path_valid()) {
return THREAD_NVM_FILE_ROOT_PATH_INVALID;
}
thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE);
int ret = thread_nvm_store_read(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), &version);
if (THREAD_NVM_FILE_SUCCESS!=ret) {
tr_info("Leader data map read failed");
thread_nvm_store_mleid_rloc_map_remove();
return ret;
}
if (LEADER_INFO_DATA_VERSION!=version) {
tr_info("Leader data map version mismatch %"PRIu32, version);
thread_nvm_store_mleid_rloc_map_remove();
return THREAD_NVM_FILE_VERSION_WRONG;
}
return ret;
}
int thread_nvm_store_mleid_rloc_map_remove(void)
{
int status;
tr_info("thread_nvm_store_leader_info_remove");
if (!ns_file_system_get_root_path()) {
return THREAD_NVM_FILE_ROOT_PATH_INVALID;
}
char lc_data_path[LEADER_INFO_STRING_LEN];
thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE);
status = remove(lc_data_path);
if (status != 0) {
return THREAD_NVM_FILE_REMOVE_ERROR;
}
return THREAD_NVM_FILE_SUCCESS;
}
int thread_nvm_store_device_configuration_write(uint8_t *mac_ptr, uint8_t *mleid_ptr)
{
thread_nvm_device_conf_t d_c;

View File

@ -67,6 +67,15 @@ typedef struct {
uint8_t mle_id[8];
} thread_nvm_device_conf_t;
typedef struct {
uint8_t mle_id[8];
} thread_nvm_rloc_map_entry_t;
typedef struct {
// mapping is in order from 0 to 63
thread_nvm_rloc_map_entry_t mleid_rloc_map[64];
} thread_nvm_mleid_rloc_map;
/* reads all fast data from nvm, if the return values is THREAD_NVM_FILE_ROOT_PATH_INVALID, the cached values are returned. */
int thread_nvm_store_fast_data_read(thread_nvm_fast_data_t* fast_data);
/* stores all fast data to nvm */
@ -87,6 +96,9 @@ int thread_nvm_store_active_configuration_remove(void);
int thread_nvm_store_device_configuration_write(uint8_t *mac_ptr, uint8_t *mleid_ptr);
int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_ptr);
int thread_nvm_store_mleid_rloc_map_write(thread_nvm_mleid_rloc_map *mleid_rloc_map);
int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map);
int thread_nvm_store_mleid_rloc_map_remove(void);
int thread_nvm_store_pending_configuration_write(void *data, uint16_t size);
int thread_nvm_store_pending_configuration_read(void *data, uint16_t size);
int thread_nvm_store_pending_configuration_remove(void);

View File

@ -91,6 +91,7 @@ static int thread_resolution_server_query_cb(int8_t service_id, uint8_t source_a
uint8_t mlEID[8];
bool proxy;
uint16_t rloc16;
uint16_t requestor_rloc;
uint32_t last_transaction_time = 0;
uint8_t *ptr;
(void)source_port;
@ -118,9 +119,11 @@ static int thread_resolution_server_query_cb(int8_t service_id, uint8_t source_a
return -1;
}
requestor_rloc = common_read_16_bit(source_address + 14);
tr_debug("Thread address query %s", trace_ipv6(target_ip_ptr));
int ret = this->query_cb_ptr(this->interface_id, target_ip_ptr, &rloc16, &proxy, &last_transaction_time, mlEID);
int ret = this->query_cb_ptr(this->interface_id, target_ip_ptr, &requestor_rloc, &rloc16, &proxy, &last_transaction_time, mlEID);
if (ret < 0) {
/* XXX "Forbidden" response? */
return -1;

View File

@ -58,7 +58,7 @@ extern "C" {
*
* /return return 0 for success, negative if unable to respond.
*/
typedef int thread_resolution_server_addr_query_cb(int8_t interface_id, const uint8_t target_addr[static 16], uint16_t *addr_out, bool *proxy, uint32_t *last_transaction_time, uint8_t *mleid_ptr);
typedef int thread_resolution_server_addr_query_cb(int8_t interface_id, const uint8_t target_addr[static 16], uint16_t *rloc, uint16_t *addr_out, bool *proxy, uint32_t *last_transaction_time, uint8_t *mleid_ptr);
#ifdef HAVE_THREAD_NEIGHBOR_DISCOVERY

View File

@ -336,10 +336,11 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
case MLE_COMMAND_ACCEPT: {
tr_info("Accept (ROUTER handler)");
uint32_t mleFrameCounter;
bool new_neigbour;
uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
/*Link accept command has an optional MLE Frame counter TLV, if this is not present use link layer frame counter TLV
@ -353,7 +354,7 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
}
//Allocate neighbor entry
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, true);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, true, &new_neigbour);
if (!entry_temp) {
return;
}
@ -361,7 +362,6 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
//Free Response
mle_service_msg_free(messageId);
entry_temp->threadNeighbor = true;
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex);
entry_temp->short_adr = shortAddress;
//when allocating neighbour entry, use MLE Frame counter if present to validate further advertisements from the neighbour
entry_temp->mle_frame_counter = mleFrameCounter;
@ -388,7 +388,7 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
}
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_neigbour);
//Copy Leader Data
*cur->thread_info->thread_leader_data = leaderData;
@ -410,6 +410,8 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
cur->thread_info->thread_leader_data->dataVersion--;
cur->thread_info->thread_leader_data->stableDataVersion--;
thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
// remove any existing rloc mapping in nvm
thread_nvm_store_mleid_rloc_map_remove();
tr_info("Router synch OK as Router");
}
@ -894,7 +896,7 @@ static int thread_attach_parent_response_build(protocol_interface_info_entry_t *
if (bufId == 0) {
return -1;
}
tr_debug("MLE ATTACHED 2. Packet");
tr_debug("Build MLE Parent response");
uint32_t keySequence;
uint8_t *ptr = mle_service_get_data_pointer(bufId);
@ -1309,12 +1311,8 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
memcpy(&ll64[8], req->euid64 , 8);
ll64[8] ^= 2;
//Allocate entry
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, req->linkMargin, ll64, false);
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, req->linkMargin, ll64, true, &new_neigbour);
if (!entry_temp) {
entry_temp = mle_class_get_entry_by_ll64(cur->id, req->linkMargin, ll64, true);
new_neigbour = true;
}
if (!entry_temp) {
//Send link reject
thread_link_reject_send(cur, ll64);
@ -1340,7 +1338,7 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
}
}
if (new_neigbour) {
mac_helper_devicetable_set(entry_temp, cur, req->frameCounter, req->keyId);
mac_helper_devicetable_set(entry_temp, cur, req->frameCounter, req->keyId, new_neigbour);
} else {
// in get response handler this will update the short address from MLE table
mlme_get_t get_req;
@ -1361,7 +1359,6 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
thread_nd_address_registration(cur, tempIPv6Address, entry_temp->short_adr, cur->mac_parameters->pan_id, entry_temp->mac64);
}
tr_debug("Response Child Id Request");
mle_attach_child_id_response_build(cur,ll64,req, entry_temp);
free_request:
@ -1474,7 +1471,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
}
// parent request received
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
entry_temp->mode = (MLE_FFD_DEV | MLE_RX_ON_IDLE | MLE_THREAD_REQ_FULL_DATA_SET);
}
@ -1595,7 +1592,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
@ -1610,6 +1607,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
mle_msg->packet_src_address[8] ^= 2;
if (!id_req) {
tr_debug("No room for child id req");
return;
}
@ -1631,6 +1629,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
(!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &id_req->frameCounter)) ||
(!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlvRequest))) {
thread_child_id_request_entry_remove(cur, id_req);
tr_debug("Illegal child id req");
return;
}
//If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
@ -1727,7 +1726,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
return;
}
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
@ -1826,12 +1825,12 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
uint16_t version, shortAddress;
uint32_t llFrameCounter;
mle_tlv_info_t requestTlv, challengeTlv;
bool createNew;
bool createNew, new_entry;
tr_info("Recv Router Accept & Request");
uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
if (messageId == 0) {
tr_debug("Not for me");
tr_debug("No matching challenge");
return;
}
@ -1854,7 +1853,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
createNew = thread_bootstrap_link_create_check(cur, shortAddress);
//Send Response
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry);
if (entry_temp) {
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
@ -1863,7 +1862,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
entry_temp->threadNeighbor = true;
entry_temp->short_adr = shortAddress;
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry);
if (entry_temp->timeout_rx) {
mle_entry_timeout_refresh(entry_temp);
} else {
@ -1900,7 +1899,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
mle_tlv_info_t addressRegisterTlv = {0};
mle_tlv_info_t challengeTlv = {0};
mle_tlv_info_t tlv_req = {0};
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status)) {
if (1 == status && thread_check_is_this_my_parent(cur, entry_temp)) {
@ -1970,7 +1969,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
case MLE_COMMAND_DATA_REQUEST: {
mle_tlv_info_t requestTlv;
tr_info("Recv Router Data Request");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
return;
}
@ -2372,6 +2371,16 @@ void thread_router_bootstrap_reed_advertisements_start(protocol_interface_info_e
cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb,timeout, cur);
}
void thread_router_bootstrap_reed_merge_advertisement(protocol_interface_info_entry_t *cur)
{
if (cur->thread_info->reedMergeAdvTimer > 1) {
return;
}
thread_reed_advertise(cur);
// 120s second timer reinitialised before next merge advertisement
cur->thread_info->reedMergeAdvTimer = THREAD_REED_MERGE_ADVERTISEMENT_INTERVAL;
}
void thread_router_bootstrap_router_id_release(protocol_interface_info_entry_t *cur)
{
tr_debug("Router ID Release");
@ -2421,6 +2430,12 @@ void thread_router_bootstrap_timer(protocol_interface_info_entry_t *cur, uint32_
}
}
if (cur->thread_info->reedMergeAdvTimer > ticks) {
cur->thread_info->reedMergeAdvTimer -= ticks;
} else {
cur->thread_info->reedMergeAdvTimer = 0;
}
if (!thread_info->leader_private_data && thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
// Non leader router checks
if (thread_info->routing.activated) {

View File

@ -45,6 +45,7 @@ struct mle_security_header;
struct buffer;
void thread_router_bootstrap_reed_advertisements_start(protocol_interface_info_entry_t *cur);
void thread_router_bootstrap_reed_merge_advertisement(protocol_interface_info_entry_t *cur);
int thread_router_bootstrap_mle_advertise(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur);
@ -101,6 +102,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_
#define thread_router_bootstrap_network_data_distribute(cur)
#define thread_router_bootstrap_routing_allowed(cur) false
#define thread_router_bootstrap_address_change_notify_send(cur)
#define thread_router_bootstrap_reed_merge_advertisement(cur)
#endif/*HAVE_THREAD_ROUTER*/

View File

@ -768,6 +768,8 @@ static void delete_link(thread_info_t *thread, thread_router_link_t *link)
thread_router_id_t id = link->router_id;
thread_routing_info_t *routing = &thread->routing;
tr_debug("delete_link: router: %x", thread_router_addr_from_id(link->router_id));
/* Remove entry from the link set */
ns_list_remove(&routing->link_set, link);
ns_dyn_mem_free(link);
@ -779,7 +781,6 @@ static void delete_link(thread_info_t *thread, thread_router_link_t *link)
ns_dyn_mem_free(route_entry);
}
}
thread_update_fast_route_table(thread);
}
@ -879,7 +880,6 @@ void thread_routing_init(thread_routing_info_t *routing)
{
ns_list_init(&routing->route_set);
ns_list_init(&routing->link_set);
routing->networkIdTimeout = NETWORK_ID_TIMEOUT;
thread_routing_reset(routing);
}
@ -887,6 +887,7 @@ void thread_routing_reset(thread_routing_info_t *routing)
{
thread_routing_free(routing);
routing->router_id_sequence_valid = false;
routing->networkIdTimeout = NETWORK_ID_TIMEOUT;
memset(routing->fast_route_table, FAST_ROUTE_INVALID_ID, sizeof routing->fast_route_table);
trickle_start(&routing->mle_advert_timer, &thread_mle_advert_trickle_params);
}

View File

@ -47,6 +47,7 @@
#include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
#include "6LoWPAN/Thread/thread_discovery.h"
#include "6LoWPAN/Thread/thread_nvm_store.h"
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
#include "MLE/mle.h"
#include "thread_meshcop_lib.h"
@ -413,6 +414,27 @@ int thread_test_key_sequence_counter_update(int8_t interface_id, uint32_t thrKey
#endif
}
int thread_test_stack_cache_reset(int8_t interface_id)
{
#ifdef HAVE_THREAD
protocol_interface_info_entry_t *cur;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
tr_warn("Invalid interface id");
return -1;
}
// Reset link information
(void) thread_nvm_store_link_info_clear();
return 0;
#else
(void)interface_id;
return -1;
#endif
}
int thread_test_key_rotation_update(int8_t interface_id, uint32_t thrKeyRotation)
{
#ifdef HAVE_THREAD

View File

@ -1014,6 +1014,12 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
case MLME_TRANSACTION_EXPIRED:
default:
tr_error("MCPS Data fail by status %u", confirm->status);
if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) {
tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address+2));
} else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
tr_info("Dest addr: %s", trace_array(buf->dst_sa.address+2, 8));
}
#ifdef HAVE_RPL
if (confirm->status == MLME_TX_NO_ACK) {
if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) {

View File

@ -48,7 +48,6 @@
#define TRACE_GROUP "icmp"
static buffer_t *icmpv6_echo_request_handler(struct buffer *buf);
static buffer_t *icmpv6_na_handler(struct buffer *buf);
/* Check to see if a message is recognisable ICMPv6, and if so, fill in code/type */
/* This used ONLY for the e.1 + e.2 tests in RFC 4443, to try to avoid ICMPv6 error loops */
@ -280,6 +279,11 @@ buffer_t *icmpv6_packet_too_big_handler(buffer_t *buf)
const uint8_t *ptr = buffer_data_pointer(buf);
uint32_t mtu = common_read_32_bit(ptr);
/* RFC 8201 - ignore MTU smaller than minimum */
if (mtu < IPV6_MIN_LINK_MTU) {
return buffer_free(buf);
}
ptr = buffer_data_strip_header(buf, 4);
/* Check source is us */
@ -481,7 +485,6 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
* interface, which we should only do in the whiteboard case.
*/
if (addr_interface_address_compare(cur, target) != 0) {
int8_t mesh_id = -1;
//tr_debug("Received NS for proxy %s", trace_ipv6(target));
proxy = true;
@ -490,7 +493,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
goto drop;
}
if (!nd_proxy_enabled_for_downstream(cur->id) || !nd_proxy_target_address_validation(cur->id, target, &mesh_id)) {
if (!nd_proxy_enabled_for_downstream(cur->id) || !nd_proxy_target_address_validation(cur->id, target)) {
goto drop;
}
}
@ -917,6 +920,80 @@ drop:
tr_warn("Redirect drop");
return buffer_free(buf);
}
static buffer_t *icmpv6_na_handler(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
uint8_t *dptr = buffer_data_pointer(buf);
uint8_t flags;
const uint8_t *target;
const uint8_t *tllao;
if_address_entry_t *addr_entry;
ipv6_neighbour_t *neighbour_entry;
//"Parse NA at IPv6\n");
if (buf->options.code != 0 || buf->options.hop_limit != 255) {
goto drop;
}
if (!icmpv6_options_well_formed_in_buffer(buf, 20)) {
goto drop;
}
// Skip the 4 reserved bytes
flags = *dptr;
dptr += 4;
// Note the target IPv6 address
target = dptr;
if (addr_is_ipv6_multicast(target)) {
goto drop;
}
/* Solicited flag must be clear if sent to a multicast address */
if (addr_is_ipv6_multicast(buf->dst_sa.address) && (flags & NA_S)) {
goto drop;
}
cur = buf->interface;
/* RFC 4862 5.4.4 DAD checks */
addr_entry = addr_get_entry(cur, target);
if (addr_entry) {
if (addr_entry->tentative) {
tr_debug("Received NA for our tentative address");
addr_duplicate_detected(cur, target);
} else {
tr_debug("NA received for our own address: %s", trace_ipv6(target));
}
goto drop;
}
if (cur->ipv6_neighbour_cache.recv_na_aro) {
const uint8_t *aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 2);
if (aro) {
icmpv6_na_aro_handler(cur, aro, buf->dst_sa.address);
}
}
/* No need to create a neighbour cache entry if one doesn't already exist */
neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, target);
if (!neighbour_entry) {
goto drop;
}
tllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_TGT_LL_ADDR, 0);
if (!tllao || !cur->if_llao_parse(cur, tllao, &buf->dst_sa)) {
buf->dst_sa.addr_type = ADDR_NONE;
}
ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, flags, buf->dst_sa.addr_type, buf->dst_sa.address);
drop:
return buffer_free(buf);
}
#endif // HAVE_IPV6_ND
buffer_t *icmpv6_up(buffer_t *buf)
@ -989,7 +1066,7 @@ buffer_t *icmpv6_up(buffer_t *buf)
case ICMPV6_TYPE_INFO_ECHO_REPLY:
ipv6_neighbour_reachability_confirmation(buf->src_sa.address, buf->interface->id);
/* no break */
/* fall through */
case ICMPV6_TYPE_ERROR_DESTINATION_UNREACH:
#ifdef HAVE_RPL_ROOT
@ -1494,79 +1571,6 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
return (buf);
}
static buffer_t *icmpv6_na_handler(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
uint8_t *dptr = buffer_data_pointer(buf);
uint8_t flags;
const uint8_t *target;
const uint8_t *tllao;
if_address_entry_t *addr_entry;
ipv6_neighbour_t *neighbour_entry;
//"Parse NA at IPv6\n");
if (buf->options.code != 0 || buf->options.hop_limit != 255) {
goto drop;
}
if (!icmpv6_options_well_formed_in_buffer(buf, 20)) {
goto drop;
}
// Skip the 4 reserved bytes
flags = *dptr;
dptr += 4;
// Note the target IPv6 address
target = dptr;
if (addr_is_ipv6_multicast(target)) {
goto drop;
}
/* Solicited flag must be clear if sent to a multicast address */
if (addr_is_ipv6_multicast(buf->dst_sa.address) && (flags & NA_S)) {
goto drop;
}
cur = buf->interface;
/* RFC 4862 5.4.4 DAD checks */
addr_entry = addr_get_entry(cur, target);
if (addr_entry) {
if (addr_entry->tentative) {
tr_debug("Received NA for our tentative address");
addr_duplicate_detected(cur, target);
} else {
tr_debug("NA received for our own address: %s", trace_ipv6(target));
}
goto drop;
}
if (cur->ipv6_neighbour_cache.recv_na_aro) {
const uint8_t *aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 2);
if (aro) {
icmpv6_na_aro_handler(cur, aro, buf->dst_sa.address);
}
}
/* No need to create a neighbour cache entry if one doesn't already exist */
neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, target);
if (!neighbour_entry) {
goto drop;
}
tllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_TGT_LL_ADDR, 0);
if (!tllao || !cur->if_llao_parse(cur, tllao, &buf->dst_sa)) {
buf->dst_sa.addr_type = ADDR_NONE;
}
ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, flags, buf->dst_sa.addr_type, buf->dst_sa.address);
drop:
return buffer_free(buf);
}
#endif // HAVE_IPV6_ND
#ifdef HAVE_IPV6_ND

View File

@ -21,15 +21,12 @@
* References:
*
* RFC 815 IP Datagram Reassembly Algorithms
* RFC 2460 Internet Protocol. Version 6 (IPv6) Specification
* RFC 3168 The Addition of Explicit Congestion Notification (ECN) to IP
* RFC 5722 Handling of Overlapping IPv6 Fragments
* RFC 6040 Tunnelling of Explicit Congestion Notification
* RFC 6145 IP/ICMP Translation Algorithm [sections on Path MTU]
* RFC 6660 Encoding Three Pre-Congestion Notification (PCN) States in the
* IP Header Using a Single Diffserv Codepoint (DSCP)
* RFC 6946 Processing of IPv6 "Atomic" Fragments
* RFC 7112 Implications of Oversized IPv6 Header Chains
* RFC 8200 Internet Protocol, Version 6 (IPv6) Specification
* RFC 8201 Path MTU Discovery for IP version 6
*/
#include "nsconfig.h"
#include "ns_types.h"
@ -656,35 +653,6 @@ buffer_t *ipv6_frag_down(buffer_t *dgram_buf)
*nh_ptr = IPV6_NH_FRAGMENT;
/* Special case for atomic fragments (caused by a small PMTU) */
/* Note that we DO have the option of actually fragmenting and obeying
* a small PMTU, which would avoid this special case.
*/
if (buffer_data_length(dgram_buf) <= IPV6_MIN_LINK_MTU - 8) {
dgram_buf = buffer_headroom(dgram_buf, 8);
if (!dgram_buf) {
return NULL;
}
/* Move unfragmentable section back 8 bytes; increase IP length field */
ip_ptr = buffer_data_reserve_header(dgram_buf, 8);
memmove(ip_ptr, ip_ptr + 8, unfrag_len);
common_write_16_bit(common_read_16_bit(ip_ptr + 4) + 8, ip_ptr + 4);
/* Write atomic fragment header into the gap */
frag_hdr = ip_ptr + unfrag_len;
frag_hdr[0] = nh;
frag_hdr[1] = 0;
common_write_16_bit(0, frag_hdr + 2);
common_write_32_bit(++dest->fragment_id, frag_hdr + 4);
return dgram_buf;
}
/* We won't fragment below minimum MTU. (Although we could...) */
if (pmtu < IPV6_MIN_LINK_MTU) {
pmtu = IPV6_MIN_LINK_MTU;
}
/* Check for silly situation - can't fit any fragment data (8 for fragment
* header, 8 for minimum fragment payload) */
if (unfrag_len + 8 + 8 > pmtu) {

View File

@ -559,7 +559,7 @@ tcp_error tcp_session_abort(tcp_session_t *tcp_session)
case TCP_STATE_FIN_WAIT_2:
case TCP_STATE_CLOSE_WAIT:
tcp_session_send_reset_to_abort_connection(tcp_session);
/* no break */
/* fall through */
case TCP_STATE_LISTEN:
case TCP_STATE_SYN_SENT:
tcp_session_delete_with_error(tcp_session, SOCKET_CONNECTION_RESET);

View File

@ -1354,14 +1354,23 @@ int8_t addr_interface_address_compare(protocol_interface_info_entry_t *cur, cons
return 0;
}
/* If link-local, that's it */
if (addr_is_ipv6_link_local(addr)) {
return -1;
/* Then check other interfaces, enforcing scope zones */
uint_fast8_t scope = addr_ipv6_scope(addr, cur);
ns_list_foreach(protocol_interface_info_entry_t, other, &protocol_interface_info_list) {
if (other != cur &&
other->zone_index[scope] == cur->zone_index[scope] &&
addr_is_assigned_to_interface(other, addr)) {
// special handling for Thread - external global-scope ULA coming in,
// which would match, but we need to restrict if that ULA is mesh-local
// on the Thread side.
if (thread_info(other) && addr_ipv6_scope(addr, other) <= IPV6_SCOPE_REALM_LOCAL) {
continue;
}
return 0;
}
}
/* Now check other interfaces */
/* TODO: should only do this if both current and other interface have forwarding enabled */
return protcol_interface_address_compare(cur, addr);
return -1;
}
int8_t addr_interface_select_source(protocol_interface_info_entry_t *cur, uint8_t *src_ptr, const uint8_t *dest, uint32_t addr_preferences)

View File

@ -340,12 +340,20 @@ struct socket *buffer_socket_set(buffer_t *buf, struct socket *socket);
/** Removes z amount of bytes from the begining of buffer
* uint8_t *buffer_data_strip_header(buffer_t *x, uint16_t z)
* */
#define buffer_data_strip_header(x,z) ((x)->buf_ptr += (z), buffer_data_pointer_after_adjustment(x))
static inline uint8_t *buffer_data_strip_header(buffer_t *x, uint16_t z)
{
x->buf_ptr += z;
return buffer_data_pointer_after_adjustment(x);
}
/** Adds z amount of bytes to the begining of buffer check if this is allowed using buffer_headroom method.
* uint8_t *buffer_data_reserve_header(buffer_t *x, uint16_t z)
* */
#define buffer_data_reserve_header(x,z) ((x)->buf_ptr -= (z), buffer_data_pointer_after_adjustment(x))
static inline uint8_t *buffer_data_reserve_header(buffer_t *x, uint16_t z)
{
x->buf_ptr -= z;
return buffer_data_pointer_after_adjustment(x);
}
/** append 1 byte to data*/
#define buffer_push_uint8(x, z) do {\

View File

@ -1301,7 +1301,7 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr
* address is valid in one of the available interfaces
* */
if (buf->src_sa.addr_type == ADDR_IPV6 &&
protcol_interface_address_compare(NULL, buf->src_sa.address) != 0) {
protocol_interface_address_compare(buf->src_sa.address) != 0) {
tr_warn("Specified source address %s is not valid",trace_ipv6(buf->src_sa.address));
ret_val = -3;
goto fail;

View File

@ -58,8 +58,10 @@ uint8_t mac_header_security_aux_header_length(uint8_t security_level, uint8_t ke
switch (keyIdmode) {
case MAC_KEY_ID_MODE_SRC8_IDX:
header_length += 4; //64-bit key source first part
/* fall through */
case MAC_KEY_ID_MODE_SRC4_IDX:
header_length += 4; //32-bit key source inline
/* fall through */
case MAC_KEY_ID_MODE_IDX:
header_length += 1;
break;
@ -128,8 +130,10 @@ void mac_header_security_parameter_set(mac_aux_security_header_t *header, const
case MAC_KEY_ID_MODE_SRC8_IDX:
keysource_len += 4; //64-bit key source first part
/* fall through */
case MAC_KEY_ID_MODE_SRC4_IDX:
keysource_len += 4; //32-bit key source inline
/* fall through */
case MAC_KEY_ID_MODE_IDX:
//Security header + 32-bit security counter + Key index
header->KeyIndex = frame_setup->KeyIndex;
@ -198,10 +202,12 @@ void mac_header_security_components_read(mac_pre_parsed_frame_t *buffer, mlme_se
break;
case MAC_KEY_ID_MODE_SRC8_IDX:
key_source_len += 4;
/* fall through */
case MAC_KEY_ID_MODE_SRC4_IDX:
key_source_len += 4;
memcpy(security_params->Keysource, ptr, key_source_len);
ptr += key_source_len;
/* fall through */
case MAC_KEY_ID_MODE_IDX:
security_params->KeyIndex = *ptr;
break;

View File

@ -386,9 +386,8 @@ int16_t mle_class_rfd_entry_count_get(int8_t interface_id)
return count;
}
mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_t linkMargin, const uint8_t *ipv6Address, bool allocateNew)
mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_t linkMargin, const uint8_t *ipv6Address, bool allocateNew, bool *new_entry_allocated)
{
// Check it really is LL64 (not LL16)
if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX , 8) != 0) {
@ -403,10 +402,9 @@ mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_
memcpy(temporary_mac64, (ipv6Address + 8), 8);
temporary_mac64[0] ^= 2;
return mle_class_get_entry_by_mac64(interface_id, linkMargin, temporary_mac64,allocateNew);
return mle_class_get_entry_by_mac64(interface_id, linkMargin, temporary_mac64, allocateNew, new_entry_allocated);
}
mle_neigh_table_entry_t *mle_class_discover_entry_by_ll64(int8_t interface_id, const uint8_t *ipv6Address)
{
@ -428,7 +426,7 @@ mle_neigh_table_entry_t *mle_class_discover_entry_by_ll64(int8_t interface_id, c
}
mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew)
mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated)
{
mle_table_class_t *mle_class_ptr = mle_table_class_discover(interface_id);
//Clean list and set function pointer call backs
@ -436,6 +434,10 @@ mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8
return NULL;
}
if (new_entry_allocated) {
*new_entry_allocated = false;
}
mle_neigh_table_entry_t *ret_val = mle_class_neighbor_get(&mle_class_ptr->mle_table, mac64, ADDR_802_15_4_LONG);
@ -454,6 +456,9 @@ mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8
topo_trace(TOPOLOGY_MLE, mac64, TOPO_ADD);
ret_val->link_margin = linkMargin << THREAD_LINK_MARGIN_SCALING;
memcpy(ret_val->mac64, mac64, 8);
if (new_entry_allocated) {
*new_entry_allocated = true;
}
}
}
return ret_val;
@ -788,7 +793,7 @@ bool mle_neigh_entry_frame_counter_update(mle_neigh_table_entry_t *entry_temp, u
frame_counter = common_read_32_bit(mle_tlv_info.dataPtr);
}
mac_helper_devicetable_set(entry_temp, cur, frame_counter, key_id);
mac_helper_devicetable_set(entry_temp, cur, frame_counter, key_id, false);
return true;
}

View File

@ -211,11 +211,11 @@ int8_t mle_class_set_new_key_pending(int8_t interface_id);
int16_t mle_class_free_entry_count_get(int8_t interface_id);
mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_t linkMargin, const uint8_t *ipv6Address, bool allocateNew);
mle_neigh_table_entry_t *mle_class_get_entry_by_ll64(int8_t interface_id, uint8_t linkMargin, const uint8_t *ipv6Address, bool allocateNew, bool *new_entry_allocated);
mle_neigh_table_entry_t *mle_class_discover_entry_by_ll64(int8_t interface_id, const uint8_t *ipv6Address);
mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew);
mle_neigh_table_entry_t *mle_class_get_entry_by_mac64(int8_t interface_id, uint8_t linkMargin, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated);
mle_neigh_table_entry_t *mle_class_get_by_link_address(int8_t interface_id, const uint8_t *address, addrtype_t type);

View File

@ -685,7 +685,8 @@ buffer_t *mpl_control_handler(buffer_t *buf, protocol_interface_info_entry_t *cu
// by its colour not being flipped.
// This is equivalent to having a "mentioned" flag, except we don't have
// to have a separate "reset" loop.
bool new_colour = --domain->colour; // smart-alec binary flip
domain->colour = !domain->colour;
bool new_colour = domain->colour;
while (ptr < end) {
if (end - ptr < 2) {

View File

@ -507,5 +507,5 @@ extern void protocol_core_dhcpv6_allocated_address_remove(protocol_interface_inf
extern void nwk_bootsrap_state_update(arm_nwk_interface_status_type_e posted_event, protocol_interface_info_entry_t *cur);
void bootsrap_next_state_kick(icmp_state_t new_state, protocol_interface_info_entry_t *cur);
int8_t protcol_interface_address_compare(protocol_interface_info_entry_t *cur, const uint8_t *addr);
int8_t protocol_interface_address_compare(const uint8_t *addr);
#endif /* _NS_PROTOCOL_H */

View File

@ -1085,10 +1085,12 @@ void protocol_core_dhcpv6_allocated_address_remove(protocol_interface_info_entry
}
}
int8_t protcol_interface_address_compare(protocol_interface_info_entry_t *cur, const uint8_t *addr)
/* XXX note that this does not perform any scope checks, so will for example match
* link local addresses on any interface - you may want addr_interface_address_compare */
int8_t protocol_interface_address_compare(const uint8_t *addr)
{
ns_list_foreach(protocol_interface_info_entry_t, other, &protocol_interface_info_list) {
if (other != cur && addr_is_assigned_to_interface(other, addr)) {
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
if (addr_is_assigned_to_interface(cur, addr)) {
return 0;
}
}

View File

@ -855,7 +855,7 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r
}
/* Even if we're not currently rooting - what if it's our address? Ignore stale info on network */
if (protcol_interface_address_compare(NULL, dodagid) == 0) {
if (addr_interface_address_compare(cur, dodagid) == 0) {
tr_info("DIO our DODAGID %s", trace_ipv6(dodagid));
/* Should we transmit poison? */
goto invalid_parent;

View File

@ -1059,7 +1059,7 @@ static bool rpl_downward_process_targets_for_transit(rpl_dodag_t *dodag, bool st
/* In Non-Storing mode, add the transit to the target, and we'll re-evaluate system routes later */
ipv6_route_table_remove_info(-1, ROUTE_RPL_DAO_SR, target);
if (transit_opt) {
if (protcol_interface_address_compare(NULL, parent) == 0) {
if (protocol_interface_address_compare(parent) == 0) {
/* If we're transit, it's on-link */
ipv6_route_add_with_info(prefix, prefix_len, interface_id, NULL, ROUTE_RPL_DAO_SR, target, 0, target->lifetime, 0);
} else {
@ -1122,7 +1122,7 @@ static void rpl_downward_link_transits_to_targets(rpl_instance_t *instance)
}
ns_list_foreach(rpl_dao_target_t, target, &instance->dao_targets) {
ns_list_foreach(rpl_dao_root_transit_t, transit, &target->info.root.transits) {
if (protcol_interface_address_compare(NULL, transit->transit) == 0) {
if (protocol_interface_address_compare(transit->transit) == 0) {
/* It points to us (the DODAG root) - mark this with NULL */
transit->parent = NULL;
target->connected = true;

View File

@ -68,7 +68,9 @@ static void fhss_beacon_tasklet_func(arm_event_s* event)
if (!fhss_structure) {
return;
}
#ifdef FEA_TRACE_SUPPORT
uint8_t parent_address[8];
#endif
fhss_clear_active_event(fhss_structure, event->event_type);
// skip the init event as there will be a timer event after
if (event->event_type == FHSS_TIMER_EVENT) {

View File

@ -68,6 +68,10 @@ typedef struct {
mle_service_class_t *mle_service = NULL;
#ifdef MLE_TEST
static mle_service_filter_cb *receive_filter_cb = NULL;
#endif
static uint8_t *mle_security_aux_header_write(uint8_t *ptr, const mle_security_header_t *auxHeader);
static void mle_security_aux_ccm_nonce_set(uint8_t *noncePtr, uint8_t *mac64, uint32_t securityFrameCounter, uint8_t securityLevel);
static uint8_t mle_security_aux_header_size(uint8_t keyIdMode);
@ -802,6 +806,13 @@ static void mle_service_socket_callback(void *cb)
mle_msg.dbm = buf->options.dbm;
mle_msg.lqi = buf->options.lqi;
#ifdef MLE_TEST
if (receive_filter_cb) {
if (!receive_filter_cb(service_handler->interface_id, &mle_msg, &securityHeader)) {
goto error_handler;
}
}
#endif
if (security_bypass) {
/* Security by pass message handler call */
service_handler->recv_security_bypass_cb(service_handler->interface_id, &mle_msg);
@ -812,7 +823,7 @@ static void mle_service_socket_callback(void *cb)
}
}
error_handler:
error_handler:
if (buf) {
buffer_free(buf);
}
@ -1199,7 +1210,7 @@ int mle_service_message_tail_get(uint16_t msgId, uint16_t tail_length)
return mle_service_buffer_tail_get(msgId,tail_length);
}
int mle_service_set_msg_timeout_parameters(uint16_t msgId, mle_message_timeout_params_t *timeout_params)
static int mle_service_timeout_fill(uint16_t msgId, mle_message_timeout_params_t *timeout_params, bool timeout_in_seconds)
{
mle_service_msg_buf_t *buffer = mle_service_buffer_find(msgId);
@ -1207,14 +1218,33 @@ int mle_service_set_msg_timeout_parameters(uint16_t msgId, mle_message_timeout_p
return -1;
}
buffer->timeout_init = randLIB_randomise_base(timeout_params->timeout_init * 10, MLE_RAND_LOW, MLE_RAND_HIGH);
buffer->timeout = buffer->timeout_init;
buffer->timeout_max = timeout_params->timeout_max * 10;
buffer->timeout_max = timeout_params->timeout_max;
buffer->retrans_max = timeout_params->retrans_max;
buffer->delayed_response = timeout_params->delay;
buffer->timeout_init = timeout_params->timeout_init;
if (timeout_in_seconds) {
buffer->timeout_max = buffer->timeout_max * 10;
buffer->timeout_init = buffer->timeout_init * 10;
}
buffer->timeout_init = randLIB_randomise_base(buffer->timeout_init, MLE_RAND_LOW, MLE_RAND_HIGH);
buffer->timeout = buffer->timeout_init;
return 0;
}
int mle_service_set_msg_timeout_parameters(uint16_t msgId, mle_message_timeout_params_t *timeout_params)
{
return mle_service_timeout_fill(msgId, timeout_params, true);
}
int mle_service_set_msg_timeout_parameters_fast(uint16_t msgId, mle_message_timeout_params_t *timeout_params)
{
return mle_service_timeout_fill(msgId, timeout_params, false);
}
int mle_service_set_msg_token_bucket_priority(uint16_t msgId)
{
mle_service_msg_buf_t *buffer = mle_service_buffer_find(msgId);
@ -1497,3 +1527,10 @@ void mle_service_set_accept_invalid_frame_counter(bool value)
}
}
#ifdef MLE_TEST
void mle_service_receive_filter_cb_set(mle_service_filter_cb *filter_cb)
{
receive_filter_cb = filter_cb;
}
#endif

View File

@ -126,8 +126,8 @@ typedef struct {
*
*/
typedef struct {
uint16_t timeout_init; /*!< Define start timeout in seconds */
uint16_t timeout_max; /*!< Define max timeout time in seconds */
uint16_t timeout_init; /*!< Define start timeout */
uint16_t timeout_max; /*!< Define max timeout time */
uint8_t retrans_max; /*!< Define max packet TX count */
uint8_t delay; /*!< 100ms Ticks for random delay */
} mle_message_timeout_params_t;
@ -189,6 +189,21 @@ typedef uint8_t * (mle_service_security_notify_cb)(int8_t interface_id, mle_secu
*/
typedef bool (mle_service_message_timeout_cb)(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
/**
* A callback for receive MLE message filtering
*
* This function will be called when MLE message is received. Only for testing purposes.
*
* \param interface_id define interface id for receiver
* \param mle_msg received MLE message
* \param security_headers messages security parameters
*
* \return true continue MLE packet processing
* \return false drop MLE packet
*
*/
typedef bool (mle_service_filter_cb)(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
/*
* Initialise server instance.
* Creates and shares socket for other mle services.
@ -568,7 +583,7 @@ int mle_service_set_msg_panid(uint16_t msgId, uint16_t panid);
/**
* Set messages timeout parameters.
*
* Messages timeout parameters define messages TX count and init timeout and max timeout values is messages delayed.
* Struct timeout_params defines messages retransmission times in seconds, retransmission count and sending delay.
* Delayed message will affect random time between 100-900ms
*
* \param msgId Message Id.
@ -576,6 +591,17 @@ int mle_service_set_msg_panid(uint16_t msgId, uint16_t panid);
*/
int mle_service_set_msg_timeout_parameters(uint16_t msgId, mle_message_timeout_params_t *timeout_params);
/**
* Set messages timeout parameters.
*
* Struct timeout_params defines messages retransmission times in 100ms, retransmission count and sending delay.
* Delayed message will affect random time between 100-900ms
*
* \param msgId Message Id.
* \param timeout_params messages transmission parameters
*/
int mle_service_set_msg_timeout_parameters_fast(uint16_t msgId, mle_message_timeout_params_t *timeout_params);
int mle_service_set_msg_rf_channel(uint16_t msgId, uint8_t channel);
int mle_service_set_msg_link_layer_security_mode(uint16_t msgId, bool use_key_id_mode_2);
@ -704,4 +730,14 @@ void mle_service_set_fragmented_msg_ll_security(bool value);
*/
void mle_service_set_accept_invalid_frame_counter(bool value);
#ifdef MLE_TEST
/**
* Set callback for MLE receiving packet filtering.
*
* If this is set, all received MLE messages will be passed to given callback.
*/
void mle_service_receive_filter_cb_set(mle_service_filter_cb *filter_cb);
#else
#define mle_service_receive_filter_cb_set(filter_cb) ((void) 0)
#endif /* MLE_TEST */
#endif /* MLE_SERVICE_API_H_ */

View File

@ -434,11 +434,11 @@ bool nd_proxy_enabled_for_upstream(int8_t interface_id)
return false;
}
bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address, int8_t *downstream_id_ptr)
bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address)
{
nd_proxy_downstream_list_s *downstream;
nd_proxy_connected_list_s *upstream = proxy_upstream_conection_get(upstream_id);
*downstream_id_ptr = -1;
if (!upstream) {
return false;
}
@ -447,7 +447,6 @@ bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address, in
downstream = proxy_cache_downstream_interface_get(downstream_entry->id, &downstream_interface_list);
if (downstream) {
if (downstream->nd_proxy_validation(downstream_entry->id, address) == 0) {
*downstream_id_ptr = downstream_entry->id;
return true;
}
}

View File

@ -125,7 +125,7 @@ bool nd_proxy_enabled_for_upstream(int8_t interface_id);
*\return true Address validated behind downstream_id_ptr interface
*\return false Unknown address for this proxy
*/
bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address, int8_t *downstream_id_ptr);
bool nd_proxy_target_address_validation(int8_t upstream_id, uint8_t *address);
/**
* Downstream interface validate prefix route on Link status from connected Upstream interface
*
@ -147,9 +147,9 @@ NS_DUMMY_DEFINITIONS_OK
#define nd_proxy_upstream_interface_unregister(interface_id) -1
#define nd_proxy_enabled_for_downstream(interface_id) false
#define nd_proxy_enabled_for_upstream(interface_id) false
#define nd_proxy_target_address_validation(upstream_id, address, downstream_id_ptr) false
#define nd_proxy_target_address_validation(upstream_id, address) false
#define nd_proxy_upstream_route_onlink(downstream_id, address) false
#define nd_proxy_target_address_validation(upstream_id, address, downstream_id_ptr) false
#endif /* HAVE_ND_PROXY */
#endif /* ND_PROXY_H_ */

View File

@ -30,3 +30,4 @@
#define HAVE_DHCPV6_SERVER
#define TCP_TEST
#define THREAD_THCI_SUPPORT
#define MLE_TEST

View File

@ -73,7 +73,6 @@ static void ipv6_destination_cache_forget_neighbour(const ipv6_neighbour_t *neig
static void ipv6_destination_release(ipv6_destination_t *dest);
static void ipv6_route_table_remove_router(int8_t interface_id, const uint8_t *addr, ipv6_route_src_t source);
static uint16_t total_metric(const ipv6_route_t *route);
static void trace_debug_print(const char *fmt, ...);
static uint8_t ipv6_route_table_count_source(int8_t interface_id, ipv6_route_src_t source);
static void ipv6_route_table_remove_last_one_from_source(int8_t interface_id, ipv6_route_src_t source);
static uint8_t ipv6_route_table_get_max_entries(int8_t interface_id, ipv6_route_src_t source);
@ -758,7 +757,7 @@ void ipv6_neighbour_cache_fast_timer(ipv6_neighbour_cache_t *cache, uint16_t tic
ipv6_neighbour_set_state(cache, cur, IP_NEIGHBOUR_UNREACHABLE);
}
}
/* no break */
/* fall through */
case IP_NEIGHBOUR_UNREACHABLE:
if (cur->retrans_count < 0xFF) {
cur->retrans_count++;

View File

@ -82,6 +82,7 @@ typedef enum ipv6_route_src {
ROUTE_THREAD,
ROUTE_THREAD_BORDER_ROUTER,
ROUTE_THREAD_PROXIED_HOST,
ROUTE_THREAD_BBR,
ROUTE_REDIRECT, /* Only occurs in destination cache */
ROUTE_MAX,
} ipv6_route_src_t;

View File

@ -20,6 +20,7 @@
#include <string.h>
#include "nsdynmemLIB.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Service_Libs/mle_service/mle_service_api.h"
#include "net_test_api.h"
#include "Common_Protocols/tcp.h"
@ -76,3 +77,8 @@ int8_t arm_nwk_test_tcp_drop_rx(int state, uint8_t count)
void arm_nwk_test_tcp_drop_reset() {
tcp_test_drop_reset();
}
void arm_nwk_test_mle_receive_filter_set(mle_service_filter_cb *response_filter_cb)
{
mle_service_receive_filter_cb_set(response_filter_cb);
}

View File

@ -656,7 +656,7 @@ int8_t socket_bind(int8_t socket, const ns_address_t *address)
return -4;
}
if (protcol_interface_address_compare(NULL, address->address) != 0) {
if (protocol_interface_address_compare(address->address) != 0) {
return -3;
}