diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 0e26b643edf..d39f913af13 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -136,8 +136,6 @@ static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void * static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { - - // Sleepy host protocol_interface_info_entry_t *cur_interface = user_data; if (thread_am_router(cur_interface)) { @@ -1069,9 +1067,7 @@ void thread_tasklet(arm_event_s *event) case THREAD_CHILD_UPDATE: tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); - if (thread_info(cur)->thread_endnode_parent) { - thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); - } + thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); break; case THREAD_ANNOUNCE_ACTIVE: { tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); @@ -1824,7 +1820,6 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[ if (prefix && dhcp_addr) { tr_debug("Delete Current Server data"); thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix); - //TODO shuold we try again or select new Server } } } @@ -2702,6 +2697,8 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) thread_border_router_network_data_update_notify(cur); thread_bbr_network_data_update_notify(cur); + thread_maintenance_timer_set(cur, THREAD_MAINTENANCE_TIMER_INTERVAL); + return 0; } diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 0716d79cf7a..a82bfebb896 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -905,6 +905,7 @@ 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 { @@ -945,6 +946,20 @@ static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16 } } +static void thread_maintenance_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) +{ + if (thread_info(cur)->thread_maintenance_timer) { + if (thread_info(cur)->thread_maintenance_timer > seconds) { + thread_info(cur)->thread_maintenance_timer -= seconds; + return; + } + } + + thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL ; + + thread_bootstrap_network_data_activate(cur); +} + void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) { uint8_t leader_address[16]; @@ -1003,6 +1018,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) } thread_router_bootstrap_timer(cur, ticks); + thread_maintenance_timer(cur, ticks); thread_border_router_seconds_timer(cur->id, ticks); thread_bbr_seconds_timer(cur->id, ticks); thread_lowpower_timer(cur, ticks); @@ -1997,5 +2013,10 @@ void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index); } +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay) +{ + thread_info(cur)->thread_maintenance_timer = delay; +} + #endif diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 09ffce3900f..753ae10d271 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -313,6 +313,7 @@ typedef struct thread_info_s { int16_t childUpdateReqTimer; uint16_t childUpdateReqMsgId; uint16_t proactive_an_timer; + uint16_t thread_maintenance_timer; //uint8_t lastValidRouteMask[8]; int8_t interface_id; //Thread Interface ID uint8_t version; @@ -441,6 +442,7 @@ bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_ void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index); bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf); +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay); #else // HAVE_THREAD NS_DUMMY_DEFINITIONS_OK diff --git a/source/6LoWPAN/Thread/thread_config.h b/source/6LoWPAN/Thread/thread_config.h index 0db796cd5d9..49a0056308b 100644 --- a/source/6LoWPAN/Thread/thread_config.h +++ b/source/6LoWPAN/Thread/thread_config.h @@ -326,6 +326,11 @@ */ #define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST +/* + * Timeout to solicit address from DHCP if previous request fails. + */ +#define THREAD_MAINTENANCE_TIMER_INTERVAL 300 + /** * Build time flag to enable THCI special traces for test harness purposes */ diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 2c108ee6e88..4ff0a64038d 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -30,6 +30,7 @@ #ifdef HAVE_THREAD #include "ns_trace.h" +#include "string.h" #include "common_functions.h" #include "NWK_INTERFACE/Include/protocol.h" #include @@ -53,6 +54,7 @@ #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_data_poll.h" +#include "Common_Protocols/ipv6.h" #include "MLE/mle.h" #include "mac_api.h" #define TRACE_GROUP "thmh" @@ -699,6 +701,54 @@ static int thread_host_child_update_response_send(protocol_interface_info_entry_ return 0; } +static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info) +{ + uint8_t context; + uint16_t length = tlv_info->tlvLen; + uint8_t *ptr = tlv_info->dataPtr; + + while (length) { + context = *ptr++; + if (context & 0x80) { + if (memcmp(ptr, entry->address + 8, 8) == 0) { + return true; + } + ptr += 8; + length -= 9; + } else { + if (memcmp(ptr, entry->address, 16) == 0) { + return true; + } + ptr += 16; + length -= 17; + } + } + + return false; + +} + +static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info) +{ + bool ret_val = true; + + ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { + 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))) { + + if (thread_address_registration_tlv_search(e, tlv_info) == false) { + tr_debug("Address %s registration to parent failed", trace_ipv6(e->address)); + addr_set_preferred_lifetime(cur, e, 0); // deprecate address + ret_val = false; + } else if (e->preferred_lifetime == 0) { + addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite + } + } + } + + return ret_val; +} + static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) { thread_leader_data_t leaderData; @@ -710,6 +760,7 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent uint64_t pending_timestamp = 0;// means no pending timestamp mac_neighbor_table_entry_t *entry_temp; bool data_request_needed = false; + mle_tlv_info_t tlv_info = {0}; tr_debug("Child update request"); entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); @@ -738,6 +789,11 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent thread_bootstrap_network_data_update(cur); } + // Check Address Registration TLV + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { // version numbers not in sync need to send data request @@ -776,6 +832,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * thread_leader_data_t leaderData = {0}; uint8_t status; bool leader_data_received; + mle_tlv_info_t tlv_info = {0}; if (cur->thread_info->thread_endnode_parent == NULL) { return; @@ -822,6 +879,10 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * tr_debug("Setting child timeout, value=%"PRIu32, timeout); } + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + tr_debug("Keep-Alive -->Respond from Parent"); mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); diff --git a/test/nanostack/unittest/stub/thread_bootstrap_stub.c b/test/nanostack/unittest/stub/thread_bootstrap_stub.c index da75fdf1a41..83ed6ac760f 100644 --- a/test/nanostack/unittest/stub/thread_bootstrap_stub.c +++ b/test/nanostack/unittest/stub/thread_bootstrap_stub.c @@ -306,3 +306,8 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, { return 0; } + +int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) +{ + return 0; +} diff --git a/test/nanostack/unittest/stub/thread_common_stub.c b/test/nanostack/unittest/stub/thread_common_stub.c index 5f47a915b4d..e9324df06fa 100644 --- a/test/nanostack/unittest/stub/thread_common_stub.c +++ b/test/nanostack/unittest/stub/thread_common_stub.c @@ -411,3 +411,9 @@ bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t { return true; } + + +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay) +{ + +}