diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index ff3fee308c0..4a97efea1b3 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -176,6 +176,128 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t return eventOS_event_send(&event); } +static void ws_nud_table_reset(protocol_interface_info_entry_t *cur) +{ + //Empty active list + ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { + ns_list_remove(&cur->ws_info->active_nud_process, entry); + } + + //Empty free list + ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->free_nud_entries) { + ns_list_remove(&cur->ws_info->free_nud_entries, entry); + } + //Add to free list to full + for (int i=0; i< ACTIVE_NUD_PROCESS_MAX; i++) { + ns_list_add_to_end(&cur->ws_info->free_nud_entries, &cur->ws_info->nud_table_entrys[i]); + } +} + +static ws_nud_table_entry_t *ws_nud_entry_get_free(protocol_interface_info_entry_t *cur) +{ + ws_nud_table_entry_t *entry = ns_list_get_first(&cur->ws_info->free_nud_entries); + if (entry) { + entry->wait_response = false; + entry->retry_count = 0; + entry->nud_process = false; + entry->timer = randLIB_get_random_in_range(1, 900); + entry->neighbor_info = NULL; + ns_list_remove(&cur->ws_info->free_nud_entries, entry); + ns_list_add_to_end(&cur->ws_info->active_nud_process, entry); + } + return entry; +} + + +void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor) +{ + ns_list_foreach(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { + if (entry->neighbor_info == neighbor) { + mac_neighbor_table_entry_t *mac_neighbor = neighbor; + ns_list_remove(&cur->ws_info->active_nud_process, entry); + ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry); + if (mac_neighbor->nud_active) { + mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_neighbor, mac_neighbor->link_lifetime); + } + + mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor); + return; + } + } +} + +static void ws_nud_state_clean(protocol_interface_info_entry_t *cur, ws_nud_table_entry_t *entry) +{ + mac_neighbor_table_entry_t *neighbor = entry->neighbor_info; + ns_list_remove(&cur->ws_info->active_nud_process, entry); + ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry); + if (neighbor->nud_active) { + neighbor->nud_active = false; + mac_neighbor_info(cur)->active_nud_process--; + } +} + +static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor) +{ + //Send NS + uint8_t ll_target[16]; + memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8); + memcpy(ll_target + 8, neighbor->mac64, 8); + ll_target[8] ^= 2; + tr_debug("NUD generate NS %u", neighbor->index); + buffer_t * buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); + if (buffer) { + protocol_push(buffer); + return true; + } + return false; +} + +void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t time_in_ms) +{ + + ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) { + if (entry->timer <= time_in_ms) { + //TX Process or timeout + if (entry->wait_response) { + //Timeout for NUD or Probe + if (entry->nud_process) { + tr_debug("NUD NA timeout"); + if (entry->retry_count < 2) { + entry->timer = randLIB_get_random_in_range(1, 900); + entry->wait_response = false; + } else { + //Clear entry from active list + ws_nud_state_clean(cur, entry); + //Remove whole entry + mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry->neighbor_info); + } + } else { + ws_nud_state_clean(cur, entry); + } + + } else { + //Random TX wait period is over + entry->wait_response = ws_nud_message_build(cur, entry->neighbor_info); + if (!entry->wait_response) { + if (entry->nud_process && entry->retry_count < 2) { + entry->timer = randLIB_get_random_in_range(1, 900); + } else { + //Clear entry from active list + //Remove and try again later on + ws_nud_state_clean(cur, entry); + } + } else { + entry->retry_count++; + entry->timer = 5001; + } + } + } else { + entry->timer -= time_in_ms; + } + } +} + static fhss_ws_neighbor_timing_info_t *ws_get_neighbor_info(const fhss_api_t *api, uint8_t eui64[8]) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_fhss_api(api); @@ -436,6 +558,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) /* Disable NUD Probes */ cur->ipv6_neighbour_cache.send_nud_probes = false; + ws_nud_table_reset(cur); + ws_bootstrap_event_discovery_start(cur); return 0; @@ -455,6 +579,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) // ws_common_reset(cur) ws_llc_reset(cur); nd_proxy_downstream_interface_unregister(cur->id); + ws_nud_table_reset(cur); return nwk_6lowpan_down(cur); } @@ -1037,17 +1162,15 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, return false; } - - uint8_t ll_target[16]; - memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8); - memcpy(ll_target + 8, entry_ptr->mac64, 8); - ll_target[8] ^= 2; - tr_debug("NUD generate NS %u", entry_ptr->index); - buffer_t * buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); - if (!buffer) { + ws_nud_table_entry_t *entry = ws_nud_entry_get_free(cur); + if (!entry) { return false; } - protocol_push(buffer); + entry->neighbor_info = entry_ptr; + + if (etx_entry->etx_samples >= WS_NEIGBOR_ETX_SAMPLE_MAX) { + entry->nud_process = true; + } return true; } diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 9dc4301cc54..7bbe37148f1 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -56,6 +56,10 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor); +void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor); + +void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t time_in_ms); + #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index cb2f196396e..54c158c4c28 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -140,6 +140,8 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur) } memset(cur->ws_info,0, sizeof(ws_info_t)); + ns_list_init(&cur->ws_info->active_nud_process); + ns_list_init(&cur->ws_info->free_nud_entries); cur->ws_info->pan_information.use_parent_bs = true; cur->ws_info->pan_information.rpl_routing_method = true; @@ -172,6 +174,7 @@ void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seco void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks) { ws_bootstrap_trickle_timer(cur, ticks); + ws_nud_active_timer(cur, 100); } @@ -180,12 +183,7 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8 //Neighbor connectected update mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL); if (mac_neighbor) { - if (mac_neighbor->nud_active) { - tr_debug("NUD Response %u", mac_neighbor->index); - mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_neighbor, mac_neighbor->link_lifetime); - } - - mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor); + ws_nud_entry_remove_active(cur, mac_neighbor); } } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 29cf8541969..fce59023032 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -20,11 +20,13 @@ #include "ns_types.h" +#include "ns_list.h" #include "fhss_api.h" #include "fhss_config.h" #include "net_fhss.h" #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_neighbor_class.h" +#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" struct ws_pan_information_s; struct ws_neighbor_class_s; @@ -40,6 +42,17 @@ typedef struct parent_info_s { uint32_t timestamp; /**< Timestamp when packet was received */ }parent_info_t; +typedef struct ws_nud_table_entry { + void *neighbor_info; + uint16_t timer; /*!< Timer which resolution is 100ms*/ + unsigned retry_count:2; + bool wait_response:1; /*!< True when NS is sended and wait NA, False when random timer is active*/ + bool nud_process; + ns_list_link_t link; +} ws_nud_table_entry_t; + +typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; + typedef struct ws_info_s { char network_name[33]; // Network name max 32 octets + terminating 0. uint16_t network_pan_id; @@ -68,7 +81,9 @@ typedef struct ws_info_s { uint8_t fhss_uc_fixed_channel; uint8_t fhss_bc_fixed_channel; uint32_t fhss_channel_mask[8]; - + ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX]; + ws_nud_table_list_t active_nud_process; + ws_nud_table_list_t free_nud_entries; struct ws_pan_information_s pan_information; ws_hopping_schedule_t hopping_schdule; struct ws_neighbor_class_s neighbor_storage;