From 22a03756deda7aee39433d96cb8d16e775a5b5b6 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 21 Dec 2017 12:58:55 +0200 Subject: [PATCH] Clear network data from lost children In some cases thread network data may contain data from children who have changed parent but the network data still point to old parent. -When original parent comes back to network then is must clean such data. -If parent does not come back then network leader will detect parent loss and clean network data from the parent and its children. --- source/6LoWPAN/Thread/thread_bootstrap.c | 12 ++-- .../6LoWPAN/Thread/thread_border_router_api.c | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 259506b9920..f4fbfc13784 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -170,19 +170,19 @@ static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t else{ tr_debug("Delete REED Neighbor"); if (thread_is_router_addr(cur->short_adr)) { - tr_debug("Router Free"); - thread_routing_remove_link(cur_interface, cur->short_adr); + tr_debug("Router Free"); + thread_routing_remove_link(cur_interface, cur->short_adr); } } } else if (thread_info(cur_interface)->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) { - tr_debug("Delete Router Neighbor"); + tr_debug("Delete Router Neighbor %x", cur->short_adr); if (thread_is_router_addr(cur->short_adr)) { - tr_debug("Router Free"); + tr_debug("Router free"); thread_routing_remove_link(cur_interface, cur->short_adr); } else if (thread_addr_is_child(mac_helper_mac16_address_get(cur_interface), cur->short_adr)) { - tr_debug("Child Free"); + tr_debug("Child free"); /* 16-bit neighbour cache entries are mesh addresses, so remain potentially valid even if an * MLE link fails. This is the only exception - if it was the link from us as a router to a * child. That means that device must be off the mesh (at that 16-bit address, at least). @@ -1163,6 +1163,8 @@ void thread_tasklet(arm_event_s *event) thread_border_router_publish(cur->id); } thread_router_bootstrap_address_change_notify_send(cur); + // Validate network data after a short period + thread_border_router_resubmit_timer_set(cur->id, 5); break; case THREAD_ATTACH_ROUTER_ID_GET_FAIL: tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_GET_FAIL"); diff --git a/source/6LoWPAN/Thread/thread_border_router_api.c b/source/6LoWPAN/Thread/thread_border_router_api.c index 8a034dacde8..3bbe07d83f8 100644 --- a/source/6LoWPAN/Thread/thread_border_router_api.c +++ b/source/6LoWPAN/Thread/thread_border_router_api.c @@ -297,6 +297,64 @@ static bool thread_border_router_local_network_data_prefix_match(thread_network_ return true; } +static void thread_border_router_children_network_data_check_and_clean(uint8_t interface_id, uint16_t child_id) +{ + uint8_t addr16_buf[2]; + + if (thread_is_router_addr(child_id)) { + // Do not check routers + return; + } + + common_write_16_bit(child_id, addr16_buf); + + if (!mle_class_get_by_link_address(interface_id, addr16_buf, ADDR_802_15_4_SHORT)) { + // Child is not our child => network data contains data from lost children, remove it + tr_debug("Remove nwk data from lost child: %04x", child_id); + thread_management_client_network_data_unregister(interface_id, child_id); + } +} + +static void thread_border_router_lost_children_nwk_data_validate(protocol_interface_info_entry_t *cur, uint16_t router_short_addr) +{ + + tr_debug("thread_border_router_lost_children_nwk_data_validate() %x", router_short_addr); + if (!thread_is_router_addr(router_short_addr)) { + // not validating children nwk data + return; + } + + thread_network_data_cache_entry_t *network_data = &cur->thread_info->networkDataStorage; + + ns_list_foreach(thread_network_data_prefix_cache_entry_t, curLP, &network_data->localPrefixList) { + /* Go throgh all routes */ + ns_list_foreach(thread_network_server_data_entry_t, curRoute, &curLP->routeList) { + if (thread_addr_is_child(router_short_addr, curRoute->routerID)) { + // Router children found + thread_border_router_children_network_data_check_and_clean(cur->id, curRoute->routerID); + } + } + + /* Go through all BR's */ + ns_list_foreach(thread_network_server_data_entry_t, curBR, &curLP->borderRouterList) { + if (thread_addr_is_child(router_short_addr, curBR->routerID)) { + // Router children found + thread_border_router_children_network_data_check_and_clean(cur->id, curBR->routerID); + } + } + } + + /* Go throgh all services */ + ns_list_foreach(thread_network_data_service_cache_entry_t, service, &network_data->service_list) { + ns_list_foreach(thread_network_data_service_server_entry_t, server, &service->server_list) { + if (thread_addr_is_child(router_short_addr, server->router_id)) { + // Router children found + thread_border_router_children_network_data_check_and_clean(cur->id, server->router_id); + } + } + } +} + static bool thread_border_router_local_network_data_service_match(thread_network_local_data_cache_entry_t *local_data, thread_network_data_service_cache_entry_t *service, uint16_t router_id) { bool instance_found = false; @@ -372,6 +430,8 @@ static bool thread_border_router_local_srv_data_in_network_data_check(protocol_i } } + thread_border_router_lost_children_nwk_data_validate(cur, router_id); + return true; }