From cfb1e81fcc695a2d9bd336913f1d3b5b46413f3f Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 14 Mar 2018 11:32:35 +0200 Subject: [PATCH 01/17] Thread tx failure handling update (#1620) When TX failure threshold is reached Thread cleaup is called, device information still remains in MLE layer causing routing problems later. Update Thread TX failure handler to clean entry information from MLE layer. MLE cleanup will trigger cleaning from MAC and Thread layers. --- source/6LoWPAN/Thread/thread_common.c | 2 +- source/6LoWPAN/Thread/thread_routing.c | 3 ++- source/6LoWPAN/adaptation_interface.c | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 936bef63058b..29b350f19f89 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -1838,7 +1838,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); } } diff --git a/source/6LoWPAN/Thread/thread_routing.c b/source/6LoWPAN/Thread/thread_routing.c index 1f8455e7a2b8..8fdf01da7b66 100644 --- a/source/6LoWPAN/Thread/thread_routing.c +++ b/source/6LoWPAN/Thread/thread_routing.c @@ -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); } diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 3cb43a30a227..230a21893c06 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -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)) { From ffb47a29ad1835c8040e5b5c079eddbd2c75706f Mon Sep 17 00:00:00 2001 From: Deepak Venugopal Date: Thu, 15 Mar 2018 13:13:15 +0200 Subject: [PATCH 02/17] additional reed advertisement (#1609) reed advertisement sent when an advertisement from lower partition is heard. --- source/6LoWPAN/Thread/thread_common.h | 1 + source/6LoWPAN/Thread/thread_constants.h | 4 +++ .../Thread/thread_mle_message_handler.c | 34 +++++++++++++------ .../6LoWPAN/Thread/thread_router_bootstrap.c | 16 +++++++++ .../6LoWPAN/Thread/thread_router_bootstrap.h | 2 ++ 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 8a70e5661bd5..74214ca9ace3 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -286,6 +286,7 @@ 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; diff --git a/source/6LoWPAN/Thread/thread_constants.h b/source/6LoWPAN/Thread/thread_constants.h index a854791ffa7d..71119051a641 100644 --- a/source/6LoWPAN/Thread/thread_constants.h +++ b/source/6LoWPAN/Thread/thread_constants.h @@ -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 diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index b68592de8bb1..6dd9a25aa7ea 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -239,22 +239,30 @@ static bool thread_router_leader_data_process(protocol_interface_info_entry_t *c return true; } +static bool thread_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data) +{ + if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) { + return true; + } + 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; + } + return false; +} + static bool thread_reed_partitions_merge(protocol_interface_info_entry_t *cur, uint16_t shortAddress, thread_leader_data_t heard_partition_leader_data) { if (thread_is_router_addr(shortAddress)) { return false; } - if (thread_extension_version_check(thread_info(cur)->version)) { - // lower weighting heard - if (thread_info(cur)->thread_leader_data->weighting > heard_partition_leader_data.weighting) { - return false; - } - // lower/same partition id heard - if (thread_info(cur)->thread_leader_data->weighting == heard_partition_leader_data.weighting && - thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId ) { - return false; - } - } else if (thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId){ + // 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; } // can merge to a higher weighting/partition id @@ -385,6 +393,10 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle if (thread_reed_partitions_merge(cur, shortAddress, leaderData)) { return; } + // REED advertisement to lower partition to help merge faster + if (thread_heard_lower_partition(cur,leaderData)) { + thread_router_bootstrap_reed_merge_advertisement(cur); + } } else { //Router if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) { diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 0bcb7c4ad19c..d02f6dbdcc7c 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -2368,6 +2368,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"); @@ -2417,6 +2427,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) { diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.h b/source/6LoWPAN/Thread/thread_router_bootstrap.h index 823655879d45..faf2f7db0d6b 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.h @@ -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*/ From 4022ad97baadb1b9ceee8fd52d4f51628996dddb Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 19 Mar 2018 14:11:04 +0200 Subject: [PATCH 03/17] Add new test API for clearing Thread stack values (#1624) Reset Thread cached values: -link configuration --- nanostack/net_thread_test.h | 13 +++++++++++++ source/6LoWPAN/Thread/thread_test_api.c | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/nanostack/net_thread_test.h b/nanostack/net_thread_test.h index 1751be8ad778..648fb79a3d7c 100644 --- a/nanostack/net_thread_test.h +++ b/nanostack/net_thread_test.h @@ -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 * diff --git a/source/6LoWPAN/Thread/thread_test_api.c b/source/6LoWPAN/Thread/thread_test_api.c index be81d1736c85..c6504beee849 100644 --- a/source/6LoWPAN/Thread/thread_test_api.c +++ b/source/6LoWPAN/Thread/thread_test_api.c @@ -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 From 1b7fdc0d8d795b29db57cabb72f2f912f3bf5e4a Mon Sep 17 00:00:00 2001 From: Tero Heinonen Date: Thu, 22 Mar 2018 08:38:56 +0200 Subject: [PATCH 04/17] Skip discovery request if MLE table is full (#1625) If MLE table is full, router must not respond to discovery request. --- source/6LoWPAN/Thread/thread_discovery.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/6LoWPAN/Thread/thread_discovery.c b/source/6LoWPAN/Thread/thread_discovery.c index ab552ccd17e7..b9e484f341a4 100644 --- a/source/6LoWPAN/Thread/thread_discovery.c +++ b/source/6LoWPAN/Thread/thread_discovery.c @@ -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 From f5530b15d73e583e384a1c3849df6f4a253bb202 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 27 Mar 2018 09:39:09 +0300 Subject: [PATCH 05/17] Thread key ID change during attach (#1627) Child ID response saves link layer frame counters that were learned when parent response was received. If key ID is changed between parent response and child id response then link layer frame counter should be cleared. --- source/6LoWPAN/Thread/thread_host_bootstrap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index e9a2ddc0faee..3b5b16e6c95e 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -832,6 +832,13 @@ 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); + + 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; From 3e8b4ce41d2af1f2b2166751d457481cef432cb1 Mon Sep 17 00:00:00 2001 From: Tero Heinonen Date: Wed, 28 Mar 2018 11:56:19 +0300 Subject: [PATCH 06/17] Multicast registration time fix (#1631) Fix for multicast registration timeouts. --- source/6LoWPAN/Thread/thread_constants.h | 2 +- source/6LoWPAN/Thread/thread_extension.c | 15 ++++++++++----- source/6LoWPAN/Thread/thread_extension_bbr.c | 12 +++++++----- .../6LoWPAN/Thread/thread_extension_constants.h | 5 +++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_constants.h b/source/6LoWPAN/Thread/thread_constants.h index 71119051a641..602f0dcf9103 100644 --- a/source/6LoWPAN/Thread/thread_constants.h +++ b/source/6LoWPAN/Thread/thread_constants.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 diff --git a/source/6LoWPAN/Thread/thread_extension.c b/source/6LoWPAN/Thread/thread_extension.c index 892e071c9a83..dd734aeb7d9b 100644 --- a/source/6LoWPAN/Thread/thread_extension.c +++ b/source/6LoWPAN/Thread/thread_extension.c @@ -271,6 +271,9 @@ int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, } if (mlr_timer_ptr) { *mlr_timer_ptr = common_read_32_bit(&found_tlv[7]); + if (*mlr_timer_ptr < THREAD_DEFAULT_MIN_MLR_TIMEOUT) { + *mlr_timer_ptr = THREAD_DEFAULT_MIN_MLR_TIMEOUT; + } } return 0; } @@ -496,14 +499,16 @@ void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t * if (addr_ipv6_multicast_scope(group->group) < IPV6_SCOPE_ADMIN_LOCAL) { return; } - // Default timer added. - group->mld_timer = added ? THREAD_ADDR_REG_TIMEOUT_BASE + randLIB_get_random_in_range(1, 30) : 0; - if (0 !=thread_extension_primary_bbr_get(interface, br_ml_addr, NULL, &mlr_timer, NULL )) { + if (0 != thread_extension_primary_bbr_get(interface, br_ml_addr, NULL, &mlr_timer, NULL )) { + // No BBR, try again later if adding address. + group->mld_timer = added ? THREAD_ADDR_REG_RETRY_INTERVAL + randLIB_get_random_in_range(1, 30) : 0; return; } - // follow the Primary BBR set timeout + Small jitter added - group->mld_timer = added ? mlr_timer: 0; + + // follow the Primary BBR set timeout. + group->mld_timer = added ? (mlr_timer - randLIB_get_random_in_range(30, 40)) : 0; + // MLR is sent only for primary BBR for now, but this might change thread_extension_mlr_req_send(interface, br_ml_addr, group->group); diff --git a/source/6LoWPAN/Thread/thread_extension_bbr.c b/source/6LoWPAN/Thread/thread_extension_bbr.c index e9fd69adf534..a2f402d07848 100644 --- a/source/6LoWPAN/Thread/thread_extension_bbr.c +++ b/source/6LoWPAN/Thread/thread_extension_bbr.c @@ -98,11 +98,10 @@ typedef struct { static NS_LIST_DEFINE(pbbr_instance_list, thread_pbbr_t, link); static NS_LIST_DEFINE(duplicate_dua_tr_list, duplicate_dua_tr_t, link); - -#define THREAD_BBR_MLR_REGISTRATION_TIMEOUT 120 +#define THREAD_BBR_MLR_REGISTRATION_TIMEOUT 600 //<* Default MLR timeout in seconds #define THREAD_BBR_DUA_REGISTRATION_TIMEOUT 3600 -#define THREAD_BBR_DUA_REGISTRATION_DELAY 5000 // 5 seconds in ms -#define THREAD_BBR_BACKBONE_PORT 5683 //<* Backbone border router +#define THREAD_BBR_DUA_REGISTRATION_DELAY 5000 // 5 seconds in ms +#define THREAD_BBR_BACKBONE_PORT 5683 //<* Backbone border router /* 0 – Successful registration @@ -608,8 +607,9 @@ static int thread_extension_bbr_mlr_cb(int8_t service_id, uint8_t source_address bbr_status = THREAD_BBR_STATUS_NOT_PRIMARY_BBR; goto send_response; } + + //check if commissioner if (2 <= thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { - //check if commissioner // Session id present must be valid tr_info("message from commissioner"); if (cur->thread_info->registered_commissioner.session_id != session_id) { @@ -630,8 +630,10 @@ static int thread_extension_bbr_mlr_cb(int8_t service_id, uint8_t source_address response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; goto send_response; } + int16_t remaining = addr_len; uint8_t *addr_ptr = addr_data_ptr; + while (remaining > 0) { //Go through all addresses if (timeout_value == 0) { diff --git a/source/6LoWPAN/Thread/thread_extension_constants.h b/source/6LoWPAN/Thread/thread_extension_constants.h index ba73134d7b92..b9af705957db 100644 --- a/source/6LoWPAN/Thread/thread_extension_constants.h +++ b/source/6LoWPAN/Thread/thread_extension_constants.h @@ -38,6 +38,11 @@ typedef struct discovery_additional_info { bool ccm_supported:1; }discovery_additional_info_t; +/** + * Minimum specified MLR timeout in seconds + */ +#define THREAD_DEFAULT_MIN_MLR_TIMEOUT 300 + /** * Default Autonomous enrollment port. */ From 2378dad5398e5c49ae3993b123c359020b44fd18 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 28 Mar 2018 12:10:30 +0300 Subject: [PATCH 07/17] Discard late Child ID responses (#1630) Child ID response can be accepted only from neighbor that was selected as parent in the latest parent scan. A device needs to discard child ID responses from old parents that are responding late. Old rloc can be released from network data when new rloc is received. --- source/6LoWPAN/Thread/thread_host_bootstrap.c | 12 +++++++++++- source/6LoWPAN/Thread/thread_network_data_storage.h | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index 3b5b16e6c95e..b6f8e0344de2 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -752,6 +752,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message 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; @@ -763,12 +764,21 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message tr_info("Received 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; } + cur->thread_info->localServerDataBase.release_old_address = true; + thread_clean_all_routers_from_neighbor_list(cur->id); thread_leader_service_stop(interface_id); thread_leader_service_leader_data_free(cur->thread_info); diff --git a/source/6LoWPAN/Thread/thread_network_data_storage.h b/source/6LoWPAN/Thread/thread_network_data_storage.h index a4d2bf017631..33671a74cf36 100644 --- a/source/6LoWPAN/Thread/thread_network_data_storage.h +++ b/source/6LoWPAN/Thread/thread_network_data_storage.h @@ -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; From 0d655ed6037ecc34582bfb698e223f6149e20258 Mon Sep 17 00:00:00 2001 From: Tero Heinonen Date: Wed, 28 Mar 2018 17:09:02 +0300 Subject: [PATCH 08/17] Update MLE receiver in Child ID req timeout error (#1634) When Child ID request times out and there is no route to leader, attaching is restarted. MLE receiver handler must be updated to avoid released thread_attach_scanned_parent pointer usage if Child ID response is received after this. --- source/6LoWPAN/Thread/thread_host_bootstrap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index b6f8e0344de2..83cc9ccc5dc7 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -1037,9 +1037,10 @@ static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, boo cur->thread_info->releaseRouterId = 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; From 32cfb6b4c8a38cd4959e0ff5ea1ba8f97c26919c Mon Sep 17 00:00:00 2001 From: katariinaliehu Date: Tue, 3 Apr 2018 10:41:23 +0300 Subject: [PATCH 09/17] Fix to partition selection rules (#1633) Fix the partition selection rule for the weight to enable merging when the heard partition weight is higher. --- source/6LoWPAN/Thread/thread_bootstrap.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index c8277df41218..3ad18e4d579a 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -333,9 +333,14 @@ int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uin /*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; + } } //Rule 1: A non-singleton Thread Network Partition always has higher priority than a singleton Thread Network Partition From a20a0bad5eae648ef5dda60ddac31bd5021ec40e Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 5 Apr 2018 11:13:53 +0300 Subject: [PATCH 10/17] Update Thread MLE neighbor list cleanup (#1637) -Device needs to clean MLE neighbors (routers and their children) when moving to new partition. Own children can be moved to new partition. -Device is not allowed to update MLE cache based on advertisements from other partition. MLE entries belonging to other partition can be removed from MLE table. -Update traces --- source/6LoWPAN/Thread/thread_bootstrap.c | 16 ++++++++-------- source/6LoWPAN/Thread/thread_bootstrap.h | 2 +- source/6LoWPAN/Thread/thread_common.c | 6 +++--- source/6LoWPAN/Thread/thread_host_bootstrap.c | 12 ++++++------ source/6LoWPAN/Thread/thread_leader_service.c | 2 +- .../6LoWPAN/Thread/thread_mle_message_handler.c | 8 +++++++- source/6LoWPAN/Thread/thread_router_bootstrap.c | 11 ++++++----- .../unittest/stub/thread_bootstrap_stub.c | 2 +- 8 files changed, 33 insertions(+), 26 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 3ad18e4d579a..cfe6b3434e6e 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -1159,14 +1159,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) -{ - 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); +void thread_neighbor_list_clean(struct protocol_interface_info_entry *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); } } } diff --git a/source/6LoWPAN/Thread/thread_bootstrap.h b/source/6LoWPAN/Thread/thread_bootstrap.h index 09b07918521b..517321704b0e 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_bootstrap.h @@ -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); diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 29b350f19f89..ff61c08f1f7d 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -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; @@ -1848,8 +1848,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); } } diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index 83cc9ccc5dc7..ebed1f7b492d 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -393,7 +393,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; } @@ -471,7 +471,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: { @@ -496,7 +496,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; } @@ -747,7 +747,7 @@ 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) { @@ -762,7 +762,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message 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); @@ -779,7 +779,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message cur->thread_info->localServerDataBase.release_old_address = true; - thread_clean_all_routers_from_neighbor_list(cur->id); + thread_neighbor_list_clean(cur); thread_leader_service_stop(interface_id); thread_leader_service_leader_data_free(cur->thread_info); thread_merge_prepare(cur); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index 4ad8f3d95d41..c72248e6dca8 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -1270,7 +1270,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; diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 6dd9a25aa7ea..1b214017fb54 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -351,6 +351,12 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); } + if (entry_temp && !thread_instance_id_matches(cur, &leaderData)) { + // Remove MLE entries that are located in other partition + mle_class_remove_entry(cur->id, entry_temp); + entry_temp = NULL; + } + // Check parent status if (!thread_attach_active_router(cur)) { //processing for non routers @@ -428,7 +434,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag 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; } diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index d02f6dbdcc7c..1af1a8b7d6ad 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -340,7 +340,7 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m 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 @@ -894,7 +894,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); @@ -1357,7 +1357,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: @@ -1591,7 +1590,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; } @@ -1606,6 +1605,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; } @@ -1627,6 +1627,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 @@ -1827,7 +1828,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; } diff --git a/test/nanostack/unittest/stub/thread_bootstrap_stub.c b/test/nanostack/unittest/stub/thread_bootstrap_stub.c index 714c2f278ab1..5f36cd0c53a1 100644 --- a/test/nanostack/unittest/stub/thread_bootstrap_stub.c +++ b/test/nanostack/unittest/stub/thread_bootstrap_stub.c @@ -257,7 +257,7 @@ int8_t thread_mle_class_init(int8_t interface_id) return 0; } -void thread_clean_all_routers_from_neighbor_list(int8_t interface_id) +void thread_neighbor_list_clean(protocol_interface_info_entry_t *cur) { } From 4f5e97dbbeac1a9cbf87fa4ea088f68ba68202d2 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 5 Apr 2018 13:52:41 +0300 Subject: [PATCH 11/17] Revert "Update Thread MLE neighbor list cleanup (#1637)" (#1639) This reverts commit a20a0bad5eae648ef5dda60ddac31bd5021ec40e. --- source/6LoWPAN/Thread/thread_bootstrap.c | 16 ++++++++-------- source/6LoWPAN/Thread/thread_bootstrap.h | 2 +- source/6LoWPAN/Thread/thread_common.c | 6 +++--- source/6LoWPAN/Thread/thread_host_bootstrap.c | 12 ++++++------ source/6LoWPAN/Thread/thread_leader_service.c | 2 +- .../6LoWPAN/Thread/thread_mle_message_handler.c | 8 +------- source/6LoWPAN/Thread/thread_router_bootstrap.c | 11 +++++------ .../unittest/stub/thread_bootstrap_stub.c | 2 +- 8 files changed, 26 insertions(+), 33 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index cfe6b3434e6e..3ad18e4d579a 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -1159,14 +1159,14 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) mac_data_poll_protocol_poll_mode_decrement(cur); } -void thread_neighbor_list_clean(struct protocol_interface_info_entry *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); +void thread_clean_all_routers_from_neighbor_list(int8_t interface_id) +{ + 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); } } } diff --git a/source/6LoWPAN/Thread/thread_bootstrap.h b/source/6LoWPAN/Thread/thread_bootstrap.h index 517321704b0e..09b07918521b 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_bootstrap.h @@ -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_neighbor_list_clean(struct protocol_interface_info_entry *cur); +void thread_clean_all_routers_from_neighbor_list(int8_t interface_id); 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); diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index ff61c08f1f7d..29b350f19f89 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -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 mle table - thread_neighbor_list_clean(cur); + //Clean routers from mle table + thread_clean_all_routers_from_neighbor_list(cur->id); // store frame counters if (cur->thread_info) { thread_nvm_fast_data_t fast_data; @@ -1848,8 +1848,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); } } diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index ebed1f7b492d..83cc9ccc5dc7 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -393,7 +393,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("No matching challenge"); + tr_debug("Not for me"); return; } @@ -471,7 +471,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m return; } - tr_debug("MLE Parent response handler"); + tr_debug("Thread MLE Parent request response Handler"); //State machine What packet should accept in this case switch (mle_msg->message_type) { case MLE_COMMAND_PARENT_RESPONSE: { @@ -496,7 +496,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("No matching challenge"); + tr_debug("Not for me"); return; } @@ -747,7 +747,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message return; } - tr_debug("Thread MLE Child ID response handler"); + tr_debug("Thread MLE Child request response Handler"); switch (mle_msg->message_type) { @@ -762,7 +762,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message thread_scanned_parent_t *scan_result = thread_info(cur)->thread_attach_scanned_parent; bool new_entry_created; - tr_info("Recv Child ID Response"); + tr_info("Received Child ID Response"); // Validate that response is coming from the scanned parent candidate memcpy(src_mac64, (mle_msg->packet_src_address + 8), 8); @@ -779,7 +779,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message cur->thread_info->localServerDataBase.release_old_address = true; - thread_neighbor_list_clean(cur); + thread_clean_all_routers_from_neighbor_list(cur->id); thread_leader_service_stop(interface_id); thread_leader_service_leader_data_free(cur->thread_info); thread_merge_prepare(cur); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index c72248e6dca8..4ad8f3d95d41 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -1270,7 +1270,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_neighbor_list_clean(cur); + thread_clean_all_routers_from_neighbor_list(cur->id); cur->mesh_callbacks = NULL; cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 1b214017fb54..6dd9a25aa7ea 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -351,12 +351,6 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); } - if (entry_temp && !thread_instance_id_matches(cur, &leaderData)) { - // Remove MLE entries that are located in other partition - mle_class_remove_entry(cur->id, entry_temp); - entry_temp = NULL; - } - // Check parent status if (!thread_attach_active_router(cur)) { //processing for non routers @@ -434,7 +428,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); if (messageId == 0) { - tr_debug("No matching challenge"); + tr_debug("Not for me"); return; } diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 1af1a8b7d6ad..d02f6dbdcc7c 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -340,7 +340,7 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); if (messageId == 0) { - tr_debug("No matching challenge"); + tr_debug("Not for me"); return; } /*Link accept command has an optional MLE Frame counter TLV, if this is not present use link layer frame counter TLV @@ -894,7 +894,7 @@ static int thread_attach_parent_response_build(protocol_interface_info_entry_t * if (bufId == 0) { return -1; } - tr_debug("Build MLE Parent response"); + tr_debug("MLE ATTACHED 2. Packet"); uint32_t keySequence; uint8_t *ptr = mle_service_get_data_pointer(bufId); @@ -1357,6 +1357,7 @@ 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: @@ -1590,7 +1591,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("No matching challenge"); + tr_debug("Not for me"); return; } @@ -1605,7 +1606,6 @@ 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; } @@ -1627,7 +1627,6 @@ 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 @@ -1828,7 +1827,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("No matching challenge"); + tr_debug("Not for me"); return; } diff --git a/test/nanostack/unittest/stub/thread_bootstrap_stub.c b/test/nanostack/unittest/stub/thread_bootstrap_stub.c index 5f36cd0c53a1..714c2f278ab1 100644 --- a/test/nanostack/unittest/stub/thread_bootstrap_stub.c +++ b/test/nanostack/unittest/stub/thread_bootstrap_stub.c @@ -257,7 +257,7 @@ int8_t thread_mle_class_init(int8_t interface_id) return 0; } -void thread_neighbor_list_clean(protocol_interface_info_entry_t *cur) +void thread_clean_all_routers_from_neighbor_list(int8_t interface_id) { } From 9c6b876266b7ff296b2df2b5ba5e3b8af29d98c3 Mon Sep 17 00:00:00 2001 From: Deepak Venugopal Date: Thu, 5 Apr 2018 13:58:13 +0300 Subject: [PATCH 12/17] added nvm support for leader router id allocation. (#1626) nvm support for MLE-ID to router id mapping maintained by the leader. This enables the leader to reallocate router ids even after restart. --- source/6LoWPAN/Thread/thread_common.c | 1 + source/6LoWPAN/Thread/thread_common.h | 3 + source/6LoWPAN/Thread/thread_leader_service.c | 56 +++++++++++++++-- source/6LoWPAN/Thread/thread_nvm_store.c | 60 +++++++++++++++++++ source/6LoWPAN/Thread/thread_nvm_store.h | 12 ++++ .../6LoWPAN/Thread/thread_router_bootstrap.c | 2 + 6 files changed, 130 insertions(+), 4 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 29b350f19f89..b3652d7b95ed 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -524,6 +524,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; } diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 74214ca9ace3..b06b9454e442 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -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 { diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index 4ad8f3d95d41..02d24e859fac 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -733,6 +733,28 @@ 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); + } + } +} + +static int thread_leader_update_mleid_rloc_map_in_nvm(protocol_interface_info_entry_t *cur) +{ + 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; + } + 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 +815,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 +871,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; @@ -1318,6 +1343,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); @@ -1500,6 +1527,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_update_mleid_rloc_map_in_nvm(cur); + } + } + thread_leader_service_router_id_valid_lifetime_update(cur, ticks); } @@ -1619,22 +1656,33 @@ 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); diff --git a/source/6LoWPAN/Thread/thread_nvm_store.c b/source/6LoWPAN/Thread/thread_nvm_store.c index fdd644e846e4..4bc337788cc9 100644 --- a/source/6LoWPAN/Thread/thread_nvm_store.c +++ b/source/6LoWPAN/Thread/thread_nvm_store.c @@ -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,62 @@ 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 (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; + } + if (THREAD_NVM_FILE_SUCCESS!=ret) { + tr_info("Leader data map read failed"); + thread_nvm_store_mleid_rloc_map_remove(); + } + 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; diff --git a/source/6LoWPAN/Thread/thread_nvm_store.h b/source/6LoWPAN/Thread/thread_nvm_store.h index d01a1719f2ee..cd160590add4 100644 --- a/source/6LoWPAN/Thread/thread_nvm_store.h +++ b/source/6LoWPAN/Thread/thread_nvm_store.h @@ -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); diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index d02f6dbdcc7c..053b14fb5de2 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -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"); } From 1060c344afe87bcc4d7756dc79f3a071de4d5632 Mon Sep 17 00:00:00 2001 From: Deepak Venugopal Date: Fri, 6 Apr 2018 09:32:34 +0300 Subject: [PATCH 13/17] file version checking handled after other errors. (#1641) --- source/6LoWPAN/Thread/thread_nvm_store.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_nvm_store.c b/source/6LoWPAN/Thread/thread_nvm_store.c index 4bc337788cc9..e0c7c9224c94 100644 --- a/source/6LoWPAN/Thread/thread_nvm_store.c +++ b/source/6LoWPAN/Thread/thread_nvm_store.c @@ -147,15 +147,18 @@ int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_m 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; } - if (THREAD_NVM_FILE_SUCCESS!=ret) { - tr_info("Leader data map read failed"); - thread_nvm_store_mleid_rloc_map_remove(); - } + return ret; } From 9e6c3a13a678fb795ce01c046ca7b1bf6eb2b472 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 6 Apr 2018 09:42:59 +0300 Subject: [PATCH 14/17] Update Thread MLE neighbor list cleanup, attempt #2 (#1640) Update Thread MLE neighbor list cleanup (#1637) -Device needs to clean MLE neighbors (routers and their children) when moving to new partition. Own children can be moved to new partition. -Device is not allowed to update MLE cache based on advertisements from other partition. MLE entries belonging to other partition can be removed from MLE table. -Update traces --- source/6LoWPAN/Thread/thread_bootstrap.c | 16 +++++++-------- source/6LoWPAN/Thread/thread_bootstrap.h | 2 +- source/6LoWPAN/Thread/thread_common.c | 6 +++--- source/6LoWPAN/Thread/thread_host_bootstrap.c | 12 +++++------ source/6LoWPAN/Thread/thread_leader_service.c | 2 +- .../Thread/thread_mle_message_handler.c | 20 ++++++++++++++----- .../6LoWPAN/Thread/thread_router_bootstrap.c | 11 +++++----- .../unittest/stub/thread_bootstrap_stub.c | 2 +- 8 files changed, 41 insertions(+), 30 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 3ad18e4d579a..cfe6b3434e6e 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -1159,14 +1159,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) -{ - 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); +void thread_neighbor_list_clean(struct protocol_interface_info_entry *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); } } } diff --git a/source/6LoWPAN/Thread/thread_bootstrap.h b/source/6LoWPAN/Thread/thread_bootstrap.h index 09b07918521b..517321704b0e 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_bootstrap.h @@ -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); diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index b3652d7b95ed..58ee80c840f6 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -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; @@ -1849,8 +1849,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); } } diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index 83cc9ccc5dc7..ebed1f7b492d 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -393,7 +393,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; } @@ -471,7 +471,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: { @@ -496,7 +496,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; } @@ -747,7 +747,7 @@ 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) { @@ -762,7 +762,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message 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); @@ -779,7 +779,7 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message cur->thread_info->localServerDataBase.release_old_address = true; - thread_clean_all_routers_from_neighbor_list(cur->id); + thread_neighbor_list_clean(cur); thread_leader_service_stop(interface_id); thread_leader_service_leader_data_free(cur->thread_info); thread_merge_prepare(cur); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index 02d24e859fac..6b43c7805c72 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -1295,7 +1295,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; diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 6dd9a25aa7ea..1f9e2d2ef250 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -327,8 +327,10 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle { mle_tlv_info_t routeTlv; thread_leader_data_t leaderData; - uint16_t shortAddress; mle_neigh_table_entry_t *entry_temp; + uint16_t shortAddress; + bool my_parent; + bool adv_from_my_partition; // Check device mode & bootstrap state if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) || @@ -346,15 +348,23 @@ 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, NULL); - if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) - && (thread_instance_id_matches(cur, &leaderData))) { + 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)); } + 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)) { //processing for non routers - if (thread_check_is_this_my_parent(cur, entry_temp)) { + if (my_parent) { //advertisement from parent if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) || (thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) { @@ -428,7 +438,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag 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; } diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 053b14fb5de2..ced6b84281ca 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -340,7 +340,7 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m 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 @@ -896,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); @@ -1359,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: @@ -1593,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; } @@ -1608,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; } @@ -1629,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 @@ -1829,7 +1830,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; } diff --git a/test/nanostack/unittest/stub/thread_bootstrap_stub.c b/test/nanostack/unittest/stub/thread_bootstrap_stub.c index 714c2f278ab1..5f36cd0c53a1 100644 --- a/test/nanostack/unittest/stub/thread_bootstrap_stub.c +++ b/test/nanostack/unittest/stub/thread_bootstrap_stub.c @@ -257,7 +257,7 @@ int8_t thread_mle_class_init(int8_t interface_id) return 0; } -void thread_clean_all_routers_from_neighbor_list(int8_t interface_id) +void thread_neighbor_list_clean(protocol_interface_info_entry_t *cur) { } From 9f85599c85aabc8fed1027fe5cf8fb96f060ae33 Mon Sep 17 00:00:00 2001 From: Kari Severinkangas Date: Fri, 6 Apr 2018 10:37:27 +0300 Subject: [PATCH 15/17] Security bits handled correctly (#1642) --- source/6LoWPAN/Thread/thread_extension.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_extension.c b/source/6LoWPAN/Thread/thread_extension.c index dd734aeb7d9b..d03d55244831 100644 --- a/source/6LoWPAN/Thread/thread_extension.c +++ b/source/6LoWPAN/Thread/thread_extension.c @@ -64,7 +64,7 @@ #define TRACE_GROUP "comm" -#define SECURITY_POLICY_CCM_ENABLED 0x04 /* Thread Commercial Commissioning Mode is enabled when this bit is set. This is Thread 1.2 feature. */ +#define SECURITY_POLICY_CCM_DISABLED 0x04 /* Thread Commercial Commissioning Mode is enabled when this bit is set. This is Thread 1.2 feature. */ typedef struct thread_extension_info { int8_t coap_service_id; @@ -581,7 +581,7 @@ bool thread_extension_enabled(protocol_interface_info_entry_t *cur) } uint16_t securityPolicy = thread_joiner_application_security_policy_get(cur->id); - if (securityPolicy & SECURITY_POLICY_CCM_ENABLED) { + if (!(securityPolicy & SECURITY_POLICY_CCM_DISABLED)) { return true; } @@ -620,11 +620,9 @@ void thread_extension_discover_response_read(discovery_response_list_t *nwk_info void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy) { - - if (version == 3 && !(securityPolicy & SECURITY_POLICY_CCM_ENABLED)) { + if (version == 3 && !(securityPolicy & SECURITY_POLICY_CCM_DISABLED)) { *data |= (uint16_t) (1 << 10); } - return; } #ifdef HAVE_THREAD_ROUTER From 564d3fe70168e65d94547f503fc7e82257d1543d Mon Sep 17 00:00:00 2001 From: Tero Heinonen Date: Fri, 6 Apr 2018 13:26:10 +0300 Subject: [PATCH 16/17] Added filter callback for MLE messages (#1638) Added test API to set callback to filter received MLE messages. --- nanostack/net_test_api.h | 8 ++++++ source/Service_Libs/mle_service/mle_service.c | 20 ++++++++++++++- .../mle_service/mle_service_api.h | 25 +++++++++++++++++++ source/configs/generic.cfg | 1 + source/libNET/src/net_test.c | 6 +++++ 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/nanostack/net_test_api.h b/nanostack/net_test_api.h index 8b797df305bc..78b2898da23b 100644 --- a/nanostack/net_test_api.h +++ b/nanostack/net_test_api.h @@ -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_ diff --git a/source/Service_Libs/mle_service/mle_service.c b/source/Service_Libs/mle_service/mle_service.c index 9bded4cb8db3..88394d02aae7 100644 --- a/source/Service_Libs/mle_service/mle_service.c +++ b/source/Service_Libs/mle_service/mle_service.c @@ -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); } @@ -1497,3 +1508,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 diff --git a/source/Service_Libs/mle_service/mle_service_api.h b/source/Service_Libs/mle_service/mle_service_api.h index 974176638567..00e61f217fd1 100644 --- a/source/Service_Libs/mle_service/mle_service_api.h +++ b/source/Service_Libs/mle_service/mle_service_api.h @@ -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. @@ -704,4 +719,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_ */ diff --git a/source/configs/generic.cfg b/source/configs/generic.cfg index 85018d8fe591..ea8216f7b76c 100644 --- a/source/configs/generic.cfg +++ b/source/configs/generic.cfg @@ -30,3 +30,4 @@ #define HAVE_DHCPV6_SERVER #define TCP_TEST #define THREAD_THCI_SUPPORT +#define MLE_TEST diff --git a/source/libNET/src/net_test.c b/source/libNET/src/net_test.c index 51c1408a056f..668ba809e4bd 100644 --- a/source/libNET/src/net_test.c +++ b/source/libNET/src/net_test.c @@ -20,6 +20,7 @@ #include #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); +} From 5af4a39d92c3d5e4596c62cbc0f8663fe4276447 Mon Sep 17 00:00:00 2001 From: Deepak Venugopal Date: Mon, 9 Apr 2018 09:50:52 +0300 Subject: [PATCH 17/17] updated mleid rloc sync in leader. (#1645) --- source/6LoWPAN/Thread/thread_common.c | 1 + source/6LoWPAN/Thread/thread_leader_service.c | 10 +++++++--- source/6LoWPAN/Thread/thread_leader_service.h | 4 ++++ .../unittest/stub/thread_leader_service_stub.c | 4 ++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 58ee80c840f6..db166f84cecc 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -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); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index 6b43c7805c72..d1e21e7f6d66 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -742,11 +742,15 @@ void thread_leader_mleid_rloc_map_populate(thread_nvm_mleid_rloc_map *mleid_rloc } } -static int thread_leader_update_mleid_rloc_map_in_nvm(protocol_interface_info_entry_t *cur) +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 -1; + 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); @@ -1533,7 +1537,7 @@ void thread_leader_service_timer(protocol_interface_info_entry_t *cur, uint32_t } else { cur->thread_info->leader_private_data->leader_nvm_sync_timer = 0; - thread_leader_update_mleid_rloc_map_in_nvm(cur); + thread_leader_mleid_rloc_map_to_nvm_write(cur); } } diff --git a/source/6LoWPAN/Thread/thread_leader_service.h b/source/6LoWPAN/Thread/thread_leader_service.h index 465a027ce23e..7eabcb302832 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.h +++ b/source/6LoWPAN/Thread/thread_leader_service.h @@ -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_ */ diff --git a/test/nanostack/unittest/stub/thread_leader_service_stub.c b/test/nanostack/unittest/stub/thread_leader_service_stub.c index 6735a6765a91..a22ee345ce21 100644 --- a/test/nanostack/unittest/stub/thread_leader_service_stub.c +++ b/test/nanostack/unittest/stub/thread_leader_service_stub.c @@ -83,3 +83,7 @@ void thread_leader_service_thread_partitition_generate(int8_t interface_id, bool void thread_leader_service_network_data_changed(protocol_interface_info_entry_t *cur, bool force_stable_update, bool force_unstable_update) { } +int thread_leader_mleid_rloc_map_to_nvm_write(protocol_interface_info_entry_t *cur) +{ + return 0; +}