diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 8bfaebc2fb2..eda9b0e185a 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -1170,6 +1170,10 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) thread_leader_service_generate_network_data(cur); } + if (thread_addresses_needs_to_be_registered(cur)) { + thread_info(cur)->childUpdateReqTimer = 1; + } + cur->bootsrap_state_machine_cnt = 0; mac_data_poll_protocol_poll_mode_decrement(cur); } diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 637eef73bd2..960accb781d 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -1736,6 +1736,96 @@ uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entr return ptr; } +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t thread_realm_local_mcast_addr[16]; + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return false; + } + + // check for addresses + ns_list_foreach(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))) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (!ctx) { + return true; + } + if (ctx->cid != 0) { + return true; + + } + } + } + + // check for multicast groups + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); + ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) + { + if (addr_ipv6_multicast_scope(entry->group) < IPV6_SCOPE_REALM_LOCAL) { + /* Skip Link Local multicast address */ + continue; + } + + if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { + /* Skip well-known realm-local all Thread nodes multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { + /* Skip All MPL Forwarders address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_NODES)) { + /* Skip Mesh local all nodes */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_ROUTERS)) { + /* Skip Mesh local all routers */ + continue; + } + return true; + } + return false; +} + +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t *address_len_ptr; + + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return ptr; + } + *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION; + address_len_ptr = ptr++; + + *address_len_ptr = 0; + + ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { + + if (*address_len_ptr > 148 ) { + // Maximum length of address registrations + continue; + } + if (!thread_addr_is_mesh_local_16(e->address, cur)) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (ctx && ctx->cid == 0) { + //Write TLV to list + *ptr++ = (ctx->cid | 0x80); + memcpy(ptr, e->address + 8, 8); + ptr += 8; + *address_len_ptr += 9; + } + } + } + return ptr; +} + uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) { uint8_t thread_realm_local_mcast_addr[16]; diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 753ae10d271..80a018e213e 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -398,6 +398,11 @@ void thread_child_mcast_entries_remove(protocol_interface_info_entry_t *cur, con uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur); uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); + +// returns true if SED/MED needs to register additional address to parent +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur); +// write mesh local address tlv +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64); thread_leader_info_t *thread_allocate_and_init_leader_private_data(void); thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality); diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index d9c18a4e5a4..a6cb6b5dbf4 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -1124,7 +1124,7 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t //Add ML-EID if ((mode & MLE_FFD_DEV) == 0) { - ptr = thread_address_registration_tlv_write(ptr, cur); + ptr = thread_ml_address_tlv_write(ptr,cur); } reqTlvCnt = 2; diff --git a/test/nanostack/unittest/stub/thread_common_stub.c b/test/nanostack/unittest/stub/thread_common_stub.c index 905ddbe3203..ec4855fe728 100644 --- a/test/nanostack/unittest/stub/thread_common_stub.c +++ b/test/nanostack/unittest/stub/thread_common_stub.c @@ -417,3 +417,7 @@ void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t { } +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur) +{ + return true; +}