From bf909d29d3b0df96692aa72afb14950e6ca9ed33 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Thu, 14 Nov 2019 02:01:30 -0800 Subject: [PATCH 01/88] Modified bbr restart mechanism when dodagid was lost Instance id is only increased when bbr stop was called by application meaning it is only used in testing purposes dodag_root_delete now only removes us from root and allows information to be retained. rpl_dodag_was_root added to check if we were root before and ignore the dodag DIOs and advertisements Fixed compile problem in bootstrap --- source/6LoWPAN/ws/ws_bbr_api.c | 9 +------- source/6LoWPAN/ws/ws_bootstrap.c | 1 + source/RPL/rpl_control.c | 14 ++++++++---- source/RPL/rpl_structures.h | 1 + source/RPL/rpl_upward.c | 22 ++++++++++--------- source/RPL/rpl_upward.h | 2 ++ .../nanostack/unittest/stub/rpl_upward_stub.c | 6 +++++ 7 files changed, 33 insertions(+), 22 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 390de439329d..f6346ef41845 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -123,7 +123,6 @@ static void ws_bbr_rpl_root_start(uint8_t *dodag_id) if (protocol_6lowpan_rpl_root_dodag) { rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag); protocol_6lowpan_rpl_root_dodag = NULL; - current_instance_id++; } protocol_6lowpan_rpl_root_dodag = rpl_control_create_dodag_root(protocol_6lowpan_rpl_domain, current_instance_id, dodag_id, &rpl_conf, rpl_conf.min_hop_rank_increase, RPL_GROUNDED | RPL_MODE_NON_STORING | RPL_DODAG_PREF(0)); @@ -141,7 +140,6 @@ static void ws_bbr_rpl_root_stop(void) if (protocol_6lowpan_rpl_root_dodag) { rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag); protocol_6lowpan_rpl_root_dodag = NULL; - current_instance_id++; } memset(current_local_prefix, 0, 8); memset(current_global_prefix, 0, 8); @@ -610,12 +608,7 @@ void ws_bbr_stop(int8_t interface_id) (void)interface_id; backbone_interface_id = -1; - if (!protocol_6lowpan_rpl_domain) { - return; - } - - rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag); - protocol_6lowpan_rpl_root_dodag = NULL; + ws_bbr_rpl_root_stop(); current_instance_id++; #else diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index f620e4d574a6..8f39db39e5af 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -896,6 +896,7 @@ static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interf */ #ifdef WISUN_1_0_ERRATA_FIX + (void)pan_information; // All messages are considered as consistent only Solicit will cause inconsistent trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); #else diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index c6854e3f4e03..af5db008159b 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -495,8 +495,13 @@ rpl_dodag_t *rpl_control_create_dodag_root(rpl_domain_t *domain, uint8_t instanc rpl_dodag_t *dodag = rpl_lookup_dodag(instance, dodagid); if (dodag) { - tr_error("Root DODAG already exists"); - return NULL; + if (rpl_dodag_am_root(dodag)) { + tr_error("Root DODAG already exists"); + return NULL; + } + + // Delete non root information and recreate dodag + rpl_delete_dodag(dodag); } dodag = rpl_create_dodag(instance, dodagid, g_mop_prf); if (!dodag) { @@ -975,8 +980,9 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r } } - /* Never listen to nodes in a DODAG we're rooting */ - if (rpl_dodag_am_root(dodag)) { + /* Never listen to nodes in a DODAG we're rooting or were root*/ + if (rpl_dodag_am_root(dodag) || + rpl_dodag_was_root(dodag)) { /* TODO - if version is newer or unordered, increment our version to be higher? */ /* Old code had this trick - actually, would need to go further. Want to listen first, then use a higher * than existing. */ diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 1d4dcc0c3771..60e815afa3d9 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -87,6 +87,7 @@ struct rpl_dodag { rpl_dodag_conf_t config; /* Configuration from DIO */ uint8_t info_version; /* Version for g_mop_prf and config */ bool root: 1; /* We are the root of this DODAG */ + bool was_root: 1; /* If we have ever been a root in this DODAG */ bool leaf: 1; /* We are a leaf in this DODAG (by policy) */ bool have_config: 1; /* We have the config */ bool used: 1; /* We have ever been a member of this DODAG? */ diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index d3e4720b0417..6e0a04a16a2d 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -638,6 +638,7 @@ rpl_dodag_t *rpl_create_dodag(rpl_instance_t *instance, const uint8_t *dodagid, memcpy(dodag->id, dodagid, 16); dodag->leaf = false; dodag->root = false; + dodag->was_root = false; dodag->have_config = false; dodag->used = false; dodag->g_mop_prf = g_mop_prf; @@ -678,15 +679,9 @@ void rpl_delete_dodag_root(rpl_dodag_t *dodag) { // This should trigger immediate poison rpl_instance_set_dodag_version(dodag->instance, NULL, RPL_RANK_INFINITE); - // Deleting DODAG is not ideal - we will just pick up adverts from our - // former children, and recreate, possibly violating the MaxRankIncrease. - // Should retain DODAG version info and just unset root flag, which will - // limit what happens when we hear adverts. - // Problem is rpl_control_create_dodag_root which can't handle the - // case where DODAG already exists. This would always be a problem if - // we'd heard adverts in between delete and create, but would be an instant - // problem without this delete. Need to fix. - rpl_delete_dodag(dodag); + // Retain DODAG version info and just unset root flag + // We have was_root still set which will drop adverts for this dodag. + dodag->root = false; } /* Convert RPL configuration to generic trickle parameters. Returns true if @@ -792,6 +787,7 @@ void rpl_dodag_set_root(rpl_dodag_t *dodag, bool root) dodag->root = root; if (root) { rpl_instance_remove_parents(dodag->instance); + dodag->was_root = true; } else { rpl_instance_run_parent_selection(dodag->instance); } @@ -803,6 +799,11 @@ bool rpl_dodag_am_root(const rpl_dodag_t *dodag) { return dodag->root; } + +bool rpl_dodag_was_root(const rpl_dodag_t *dodag) +{ + return dodag->was_root; +} #endif void rpl_dodag_set_leaf(rpl_dodag_t *dodag, bool leaf) @@ -1381,7 +1382,8 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) return; } - if (instance->current_dodag_version && instance->current_dodag_version->dodag->root) { + if (instance->current_dodag_version && + (instance->current_dodag_version->dodag->root || instance->current_dodag_version->dodag->was_root)) { return; } diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index 2780f6729a96..cd920606b38e 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -97,8 +97,10 @@ uint8_t rpl_dodag_mop(const rpl_dodag_t *dodag); void rpl_dodag_set_root(rpl_dodag_t *dodag, bool root); #ifdef HAVE_RPL_ROOT bool rpl_dodag_am_root(const rpl_dodag_t *dodag); +bool rpl_dodag_was_root(const rpl_dodag_t *dodag); #else #define rpl_dodag_am_root(dodag) false +#define rpl_dodag_was_root(dodag) false #endif uint8_t rpl_dodag_get_version_number_as_root(const rpl_dodag_t *dodag); void rpl_dodag_set_version_number_as_root(rpl_dodag_t *dodag, uint8_t number); diff --git a/test/nanostack/unittest/stub/rpl_upward_stub.c b/test/nanostack/unittest/stub/rpl_upward_stub.c index ee761a4a33df..cd4cdaadf32a 100644 --- a/test/nanostack/unittest/stub/rpl_upward_stub.c +++ b/test/nanostack/unittest/stub/rpl_upward_stub.c @@ -308,6 +308,12 @@ void rpl_dodag_set_root(rpl_dodag_t *dodag, bool root) bool rpl_dodag_am_root(const rpl_dodag_t *dodag) { + return true; +} + +bool rpl_dodag_was_root(const rpl_dodag_t *dodag) +{ + return true; } void rpl_dodag_set_leaf(rpl_dodag_t *dodag, bool leaf) From e659a01241fe317651461baa0b8e3a6a996e193f Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 19 Nov 2019 12:55:00 +0200 Subject: [PATCH 02/88] Fixed compile warning for may uninitialized usage. Change-Id: I50a59966e64a151f68ba168f30e07c457b79b3e8 --- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index a97570675a67..1ea990f2e054 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1543,7 +1543,7 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt mac_header_information_elements_preparation(buffer); mcps_generic_sequence_number_allocate(rf_ptr, buffer); - mlme_key_descriptor_t *key_desc; + mlme_key_descriptor_t *key_desc = NULL; if (buffer->fcf_dsn.securityEnabled) { bool increment_framecounter = false; //Remember to update security counter here! @@ -1600,7 +1600,7 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt tr_debug("Too Long %u, %u pa %u header %u mic %u", frame_length, mac_payload_length, buffer->mac_header_length_with_security, buffer->security_mic_len, dev_driver->phy_MTU); buffer->status = MLME_FRAME_TOO_LONG; //decrement security counter - if (buffer->fcf_dsn.securityEnabled) { + if (key_desc) { mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc); } return -1; @@ -1716,7 +1716,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in ccm_globals_t ccm_ptr; mac_pre_build_frame_t *buffer = &rf_ptr->enhanced_ack_buffer; - mlme_key_descriptor_t *key_desc; + mlme_key_descriptor_t *key_desc = NULL; if (buffer->fcf_dsn.securityEnabled) { //Remember to update security counter here! @@ -1755,7 +1755,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in if ((frame_length) > ack_mtu_size - 2) { buffer->status = MLME_FRAME_TOO_LONG; - if (buffer->fcf_dsn.securityEnabled) { + if (key_desc) { //decrement security counter mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc); ccm_free(&ccm_ptr); From 21d9c24acddaba55f4a5f0c780d9364ddf860a70 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 19 Nov 2019 13:01:42 +0200 Subject: [PATCH 03/88] DHCP server address allocated pointer init fix. Change-Id: I331b31f4d695830cabfffa67145faefd5b198d2b --- source/DHCPv6_Server/DHCPv6_Server_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index bd606db11fe9..c2f567e40f76 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -87,7 +87,7 @@ static void DHCP_server_service_timer_stop(void) int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_reply_packet_s *replyPacket, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, dhcpv6_gua_response_t *response, bool allocateNew) { - dhcpv6_alloacted_address_entry_t *dhcp_allocated_address; + dhcpv6_alloacted_address_entry_t *dhcp_allocated_address = NULL; dhcpv6_ia_non_temporal_address_s nonTemporalAddress; bool address_allocated = false; //Validate Client DUID From 66bfd985fb89db1fe438a90ffc16992544218b49 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 19 Nov 2019 13:08:33 +0200 Subject: [PATCH 04/88] Fixed trace printing warnings. Change-Id: I5f37fa9f5e7efdf492258b74762398d82428bca1 --- source/6LoWPAN/ws/ws_bootstrap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 8f39db39e5af..26f6454f566b 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1190,7 +1190,7 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter if (ws_bootstrap_state_discovery(cur) && cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin + 50) { cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; - tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10)); + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); } } @@ -2295,7 +2295,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c); cur->bootsrap_state_machine_cnt = time_to_solicit + cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; - tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10)); + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); } // Start authentication @@ -2356,7 +2356,7 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_ // Go back for network scanning ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, cur->ws_info->trickle_params_pan_discovery.Imin >> 1); - tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10)); + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); } else { tr_debug("authentication failed"); // What else to do to start over again... @@ -2728,7 +2728,7 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) if (!selected_parent_ptr) { // Next check will be after one trickle cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; - tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10)); + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); return; } tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id); From 2b1dfb90ed7b697c0f726f977b7c4f52a31eaa72 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Tue, 19 Nov 2019 05:20:13 -0800 Subject: [PATCH 05/88] Slaac address can be recreated after root stop bbr_stop will clear all data related to RPL root start Stops the DHCP server at bbr stop --- source/6LoWPAN/ws/ws_bbr_api.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index f6346ef41845..b658c0c434f2 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -175,11 +175,24 @@ int ws_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handl static if_address_entry_t *ws_bbr_slaac_generate(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix) { - if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, ula_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED); + if_address_entry_t *add_entry = NULL; + const uint8_t *address; + + address = addr_select_with_prefix(cur, ula_prefix, 64, 0); + if (address) { + // Address already exists for this prefix find the entry + add_entry = addr_get_entry(cur, address); + } + + if (!add_entry) { + add_entry = icmpv6_slaac_address_add(cur, ula_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED); + } if (!add_entry) { tr_err("ula create failed"); return NULL; } + // Set the timeouts for this address and policy + icmpv6_slaac_prefix_update(cur, ula_prefix, 64, 0xffffffff, 0xffffffff); addr_policy_table_add_entry(ula_prefix, 64, 2, WS_NON_PREFFRED_LABEL); return add_entry; } @@ -382,6 +395,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) if (memcmp(local_prefix, ADDR_UNSPECIFIED, 8) != 0) { if (!ws_bbr_slaac_generate(cur, local_prefix)) { + // Address creation failed return; } @@ -605,8 +619,16 @@ void ws_bbr_stop(int8_t interface_id) { #ifdef HAVE_WS_BORDER_ROUTER - (void)interface_id; backbone_interface_id = -1; + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + + ws_bbr_slaac_remove(cur, current_dodag_id); + if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) { + ws_bbr_slaac_remove(cur, current_local_prefix); + } + if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) { + ws_bbr_dhcp_server_stop(cur, current_global_prefix); + } ws_bbr_rpl_root_stop(); current_instance_id++; From 385ae1428414528cf699dd4461ceb72b286ca829 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 20 Nov 2019 11:03:53 +0200 Subject: [PATCH 06/88] WS bootstrap: print MAC address --- source/6LoWPAN/ws/ws_bootstrap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 26f6454f566b..a9e9037bba3b 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -641,8 +641,9 @@ static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entr mac64[0] |= 2; //Set Local Bit mac64[0] &= ~1; //Clear multicast bit - tr_info("Generated random MAC %s", trace_array(mac64, 8)); + tr_info("Generated random MAC address"); } + tr_info("MAC address: %s", trace_array(mac64, 8)); mac_helper_mac64_set(cur, mac64); memcpy(cur->iid_eui64, mac64, 8); From 930741617f90cd20293c65dbafd6ee4733ab7aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Wed, 13 Nov 2019 11:24:04 +0200 Subject: [PATCH 07/88] Added check to prevent installing new GTK to used index using GKH Border router now records what GTKs it has installed to supplicant using group key handshake. If a GTK for an index (0, 1, 2 or 3), would be updated to new value second time with GKH, border router initiates 4WH instead of GKH, to update also PTK. This makes re-playing GKH messages harder, since both replay counters and keys for old messages, are invalid. On normal border router PMK/PTK/GTK update cycle, this is already forced also without changes in this commit, since default GTK lifetime is one month and PTK is two monts. For a specific GTK index, the PTK will be updated several times, before the GTK index is re-used. --- source/6LoWPAN/ws/ws_pae_auth.c | 32 +++++++-- .../fwh_sec_prot/auth_fwh_sec_prot.c | 3 +- .../gkh_sec_prot/auth_gkh_sec_prot.c | 3 + source/Security/protocols/sec_prot_keys.c | 72 ++++++++++++++++++- source/Security/protocols/sec_prot_keys.h | 47 +++++++++++- 5 files changed, 146 insertions(+), 11 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index aeac10653142..01ffea56039d 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -70,6 +70,9 @@ nanostack monitor */ #define SUPPLICANT_NUMBER_TO_PURGE 5 +// Short GTK lifetime value, for GTK install check +#define SHORT_GTK_LIFETIME 10 * 3600 // 10 hours + typedef struct { ns_list_link_t link; /**< Link */ kmp_service_t *kmp_service; /**< KMP service */ @@ -113,7 +116,7 @@ static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e resu static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr); static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys); static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry); -static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry); +static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry); static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry); static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp); @@ -666,7 +669,9 @@ static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth) sec_prot_keys_gtk_clear(pae_auth->next_gtks, next_gtk_index); sec_prot_keys_gtk_set(pae_auth->next_gtks, next_gtk_index, gtk_value, 0); } else { - randLIB_get_n_bytes_random(gtk_value, GTK_LEN); + do { + randLIB_get_n_bytes_random(gtk_value, GTK_LEN); + } while (sec_prot_keys_gtk_valid_check(gtk_value) < 0); } // Gets latest installed key lifetime and adds GTK expire offset to it @@ -910,7 +915,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup supp_entry->retry_ticks = 0; // Get next protocol based on what keys supplicant has - kmp_type_e next_type = ws_pae_auth_next_protocol_get(supp_entry); + kmp_type_e next_type = ws_pae_auth_next_protocol_get(pae_auth, supp_entry); if (next_type == KMP_TYPE_NONE) { // All done @@ -969,7 +974,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup kmp_api_create_request(new_kmp, next_type, &supp_entry->addr, &supp_entry->sec_keys); } -static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry) +static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry) { kmp_type_e next_type = KMP_TYPE_NONE; sec_prot_keys_t *sec_keys = &supp_entry->sec_keys; @@ -999,9 +1004,22 @@ static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry) if (gtk_index >= 0) { if (next_type == KMP_TYPE_NONE && gtk_index >= 0) { - // Update just GTK - next_type = IEEE_802_11_GKH; - tr_info("PAE start GKH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + + /* Check if the PTK has been already used to install GTK to specific index and if it + * has been, trigger 4WH to update also the PTK. This prevents writing multiple + * GTK keys to same index using same PTK. + */ + if (pae_auth->timer_settings->gtk_expire_offset > SHORT_GTK_LIFETIME && + sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_keys, gtk_index)) { + // start 4WH towards supplicant + next_type = IEEE_802_11_4WH; + sec_keys->ptk_mismatch = true; + tr_info("PAE start 4WH due to GTK index re-use, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + } else { + // Update just GTK + next_type = IEEE_802_11_GKH; + tr_info("PAE start GKH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + } } tr_info("PAE update GTK index: %i, eui-64: %s", gtk_index, trace_array(supp_entry->addr.eui_64, 8)); diff --git a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c index 5c0a48393d14..02b32b729f20 100644 --- a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c +++ b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c @@ -414,7 +414,8 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) if (auth_fwh_sec_prot_mic_validate(prot) < 0) { return; } - + // PTK is fresh for installing any GTKs + sec_prot_keys_ptk_installed_gtk_hash_clear_all(prot->sec_keys); // If GTK was inserted set it valid sec_prot_keys_gtkl_from_gtk_insert_index_set(prot->sec_keys); // Reset PTK mismatch diff --git a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c index 50a9691b33b6..b4206f69b4f3 100644 --- a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c +++ b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c @@ -315,6 +315,9 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot) sec_prot_timer_trickle_start(&data->common, &gkh_trickle_params); sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2); + + // Store the hash for to-be installed GTK as used for the PTK + sec_prot_keys_ptk_installed_gtk_hash_set(prot->sec_keys); break; // Wait GKH message 2 diff --git a/source/Security/protocols/sec_prot_keys.c b/source/Security/protocols/sec_prot_keys.c index 9a0d4c8a434f..cdcc31de3269 100644 --- a/source/Security/protocols/sec_prot_keys.c +++ b/source/Security/protocols/sec_prot_keys.c @@ -38,6 +38,8 @@ #define TRACE_GROUP "spke" +static const uint8_t empty_hash[GTK_HASH_LEN] = {0}; + sec_prot_keys_t *sec_prot_keys_create(sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs) { sec_prot_keys_t *sec_keys = ns_dyn_mem_alloc(sizeof(sec_prot_keys_t)); @@ -67,6 +69,7 @@ void sec_prot_keys_init(sec_prot_keys_t *sec_keys, sec_prot_gtk_keys_t *gtks, co sec_keys->ptk_eui_64_set = false; sec_keys->pmk_mismatch = false; sec_keys->ptk_mismatch = false; + sec_prot_keys_ptk_installed_gtk_hash_clear_all(sec_keys); } void sec_prot_keys_delete(sec_prot_keys_t *sec_keys) @@ -581,9 +584,22 @@ void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhas } } -void sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash) +int8_t sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash) { + return sec_prot_lib_gtkhash_generate(gtk, gtk_hash); +} + +int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk) +{ + uint8_t gtk_hash[8]; sec_prot_lib_gtkhash_generate(gtk, gtk_hash); + + // Checks if GTK hash for the GTK would be all zero + if (memcmp(gtk_hash, empty_hash, GTK_HASH_LEN) == 0) { + return -1; + } + + return 0; } gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash) @@ -639,7 +655,6 @@ gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t bool sec_prot_keys_gtk_hash_empty(uint8_t *gtkhash) { - const uint8_t empty_hash[GTK_HASH_LEN] = {0}; if (memcmp(gtkhash, empty_hash, GTK_HASH_LEN) == 0) { return true; } else { @@ -783,4 +798,57 @@ uint8_t sec_prot_keys_gtk_count(sec_prot_gtk_keys_t *gtks) return count; } +void sec_prot_keys_ptk_installed_gtk_hash_clear_all(sec_prot_keys_t *sec_keys) +{ + for (uint8_t index = 0; index < GTK_NUM; index++) { + memset(sec_keys->ins_gtk_hash[sec_keys->gtk_set_index].hash, 0, INS_GTK_HASH_LEN); + } + sec_keys->ins_gtk_hash_set = 0; +} + +void sec_prot_keys_ptk_installed_gtk_hash_set(sec_prot_keys_t *sec_keys) +{ + if (sec_keys->gtk_set_index >= 0) { + uint8_t *gtk = sec_prot_keys_gtk_get(sec_keys->gtks, sec_keys->gtk_set_index); + if (!gtk) { + return; + } + uint8_t gtk_hash[GTK_HASH_LEN]; + if (sec_prot_keys_gtk_hash_generate(gtk, gtk_hash) < 0) { + return; + } + /* Store two byte hash. This is long enough for the GTK installed check, since + * possible conflict between hashes causes only that 4WH is initiated/is not + * initiated instead of GKH. + */ + memcpy(sec_keys->ins_gtk_hash[sec_keys->gtk_set_index].hash, gtk_hash, INS_GTK_HASH_LEN); + sec_keys->ins_gtk_hash_set |= (1 << sec_keys->gtk_set_index); + } +} + +bool sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_prot_keys_t *sec_keys, uint8_t gtk_index) +{ + if ((sec_keys->ins_gtk_hash_set & (1 << sec_keys->gtk_set_index)) == 0) { + return false; + } + + uint8_t *gtk = sec_prot_keys_gtk_get(sec_keys->gtks, gtk_index); + if (!gtk) { + return false; + } + + // Calculated GTK hash for the current GTK on the defined index + uint8_t gtk_hash[GTK_HASH_LEN]; + if (sec_prot_keys_gtk_hash_generate(gtk, gtk_hash) < 0) { + return false; + } + + // If PTK has been used to install different GTK to index than the current one, trigger mismatch + if (memcmp(sec_keys->ins_gtk_hash[sec_keys->gtk_set_index].hash, gtk_hash, INS_GTK_HASH_LEN) != 0) { + return true; + } + + return false; +} + #endif /* HAVE_WS */ diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index 4a14fc2b6ffc..3b3ae88c7b85 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -54,6 +54,7 @@ #define GTK_HASH_LEN 8 #define GTK_ALL_HASHES_LEN GTK_HASH_LEN * GTK_NUM +#define INS_GTK_HASH_LEN 2 #define PMK_LIFETIME_INSTALL 0xFFFFF #define PTK_LIFETIME_INSTALL 0xFFFFF @@ -71,18 +72,24 @@ typedef struct { bool updated: 1; /**< Group Transient Keys has been updated */ } sec_prot_gtk_keys_t; +typedef struct { + uint8_t hash[INS_GTK_HASH_LEN]; /**< Inserted GTKs for a PTK hash */ +} sec_prot_gtk_hash_t; + // Security key data typedef struct { uint64_t pmk_key_replay_cnt; /**< Pairwise Master Key replay counter */ uint8_t pmk[PMK_LEN]; /**< Pairwise Master Key (256 bits) */ uint8_t ptk[PTK_LEN]; /**< Pairwise Transient Key (384 bits) */ uint8_t ptk_eui_64[8]; /**< Remote EUI-64 used to derive PTK or NULL */ + sec_prot_gtk_hash_t ins_gtk_hash[GTK_NUM]; /**< Hashes for inserted GTKs for a PTK */ sec_prot_gtk_keys_t *gtks; /**< Group Transient Keys */ const sec_prot_certs_t *certs; /**< Certificates */ uint32_t pmk_lifetime; /**< PMK lifetime in seconds */ uint32_t ptk_lifetime; /**< PTK lifetime in seconds */ uint8_t gtkl; /**< Remote GTKL information */ int8_t gtk_set_index; /**< Index of GTK to set */ + uint8_t ins_gtk_hash_set: 4; /**< Hash for inserted GTKs for a PTK set */ bool pmk_set: 1; /**< Pairwise Master Key set */ bool ptk_set: 1; /**< Pairwise Transient Key set */ bool pmk_key_replay_cnt_set: 1; /**< Pairwise Master Key replay counter set */ @@ -649,8 +656,20 @@ void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtk_ha * \param gtk GTK key * \param gtk_hash GTK hash for a GTK * + * \return < 0 failure + * \return >= 0 success */ -void sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash); +int8_t sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash); + +/** + * sec_prot_keys_gtk_valid_check check if GTK is valid + * + * \param gtk GTK key + * + * \return < 0 failure + * \return >= 0 success + */ +int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk); /** * sec_prot_keys_gtks_hash_update update GTKs based on GTK hash @@ -751,4 +770,30 @@ int8_t sec_prot_keys_gtk_install_index_get(sec_prot_gtk_keys_t *gtks); */ uint8_t sec_prot_keys_gtk_count(sec_prot_gtk_keys_t *gtks); +/** + * sec_prot_keys_ptk_installed_gtk_hash_clear_all clear GTK hashes of the GTKs that has been installed + * to supplicant using the PTK + * \param sec_keys security keys + * + */ +void sec_prot_keys_ptk_installed_gtk_hash_clear_all(sec_prot_keys_t *sec_keys); + +/** + * sec_prot_keys_ptk_installed_gtk_hash_set set GTK hash of the GTK that has been installed + * to supplicant using the current PTK + * + * \param sec_keys security keys + * + */ +void sec_prot_keys_ptk_installed_gtk_hash_set(sec_prot_keys_t *sec_keys); + +/** + * sec_prot_keys_ptk_installed_gtk_hash_set check if PTK is being used to store new GTK for the index + * for the supplicant i.e. GTK hash would change + * + * \param sec_keys security keys + * + */ +bool sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_prot_keys_t *sec_keys, uint8_t gtk_index); + #endif /* SEC_PROT_KEYS_H_ */ From 5c2fc55f0e959463d48c79280b4f099249f49dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Wed, 20 Nov 2019 17:13:29 +0200 Subject: [PATCH 08/88] Corrected frame counter handling on re-discovery Frame counters were not correctly set when key was inserted after re-discovery (where it had been removed from MAC). Now there are own values for stored and current frame counters to fix that. Also added check that frame counters are read only once from nvm. --- source/6LoWPAN/ws/ws_pae_controller.c | 34 +++++++++++++++++------ source/Security/protocols/sec_prot_keys.h | 3 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 6db0877be7f6..383af27ba946 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -88,6 +88,7 @@ typedef struct { bool gtks_set : 1; /**< GTKs are set */ bool gtkhash_set : 1; /**< GTK hashes are set */ bool key_index_set : 1; /**< NW key index is set */ + bool frame_counter_read : 1; /**< Frame counters has been read */ } pae_controller_t; typedef struct { @@ -380,9 +381,11 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_ // Read current counter from MAC uint32_t curr_frame_counter; controller->nw_frame_counter_read(controller->interface_ptr, &curr_frame_counter, i); + // If stored frame counter is greater than MAC counter if (controller->frame_counters.counter[i].frame_counter > curr_frame_counter) { - tr_debug("Frame counter set: %i, stored %"PRIu32" current: %"PRIu32"", i, controller->frame_counters.counter[i].frame_counter, curr_frame_counter); + tr_debug("Frame counter set: %i, stored %"PRIu32" current: %"PRIu32"", i, + controller->frame_counters.counter[i].frame_counter, curr_frame_counter); curr_frame_counter = controller->frame_counters.counter[i].frame_counter; // Updates MAC frame counter controller->nw_frame_counter_set(controller->interface_ptr, curr_frame_counter, i); @@ -474,6 +477,9 @@ void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface return; } + /* Checks if frame counters needs to be stored when keys are removed */ + ws_pae_controller_frame_counter_store(controller, true); + tr_info("NW keys remove"); nw_key_t *nw_key = controller->nw_key; @@ -589,6 +595,7 @@ static void ws_pae_controller_data_init(pae_controller_t *controller) controller->gtks_set = false; controller->gtkhash_set = false; controller->key_index_set = false; + controller->frame_counter_read = false; controller->gtk_index = -1; controller->network_name = NULL; controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL; @@ -602,6 +609,11 @@ static void ws_pae_controller_data_init(pae_controller_t *controller) static void ws_pae_controller_frame_counter_read(pae_controller_t *controller) { + if (controller->frame_counter_read) { + return; + } + controller->frame_counter_read = true; + // Read frame counters if (ws_pae_controller_nvm_frame_counter_read(&controller->frame_counters) >= 0) { bool updated = false; @@ -610,6 +622,8 @@ static void ws_pae_controller_frame_counter_read(pae_controller_t *controller) if (controller->frame_counters.counter[index].set) { // Increments frame counters controller->frame_counters.counter[index].frame_counter += FRAME_COUNTER_INCREMENT; + controller->frame_counters.counter[index].stored_frame_counter = + controller->frame_counters.counter[index].frame_counter; tr_info("Read frame counter: index %i value %"PRIu32"", index, controller->frame_counters.counter[index].frame_counter); @@ -620,7 +634,6 @@ static void ws_pae_controller_frame_counter_read(pae_controller_t *controller) // Writes incremented frame counters ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, &controller->frame_counters); ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer); - //ws_pae_controller_frame_counter_write(controller, &controller->frame_counters); } } } @@ -630,6 +643,7 @@ static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counte for (uint8_t index = 0; index < GTK_NUM; index++) { memset(frame_counters->counter[index].gtk, 0, GTK_LEN); frame_counters->counter[index].frame_counter = 0; + frame_counters->counter[index].stored_frame_counter = 0; frame_counters->counter[index].set = false; } } @@ -689,9 +703,6 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr) return -1; } - // Stores frame counter - ws_pae_controller_frame_counter_store(controller, false); - // Removes network keys from PAE controller and MAC ws_pae_controller_nw_keys_remove(interface_ptr); @@ -1241,18 +1252,25 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool // If frame counter for the network key has already been stored if (entry->frame_counters.counter[i].set && memcmp(entry->nw_key[i].gtk, entry->frame_counters.counter[i].gtk, GTK_LEN) == 0) { + + if (curr_frame_counter > entry->frame_counters.counter[i].frame_counter) { + entry->frame_counters.counter[i].frame_counter = curr_frame_counter; + } + uint32_t frame_counter = entry->frame_counters.counter[i].frame_counter; + // If threshold check is disabled or frame counter has advanced for the threshold value, stores the new value if (!use_threshold || - curr_frame_counter > entry->frame_counters.counter[i].frame_counter + FRAME_COUNTER_STORE_THRESHOLD) { - entry->frame_counters.counter[i].frame_counter = curr_frame_counter; + frame_counter > entry->frame_counters.counter[i].stored_frame_counter + FRAME_COUNTER_STORE_THRESHOLD) { + entry->frame_counters.counter[i].stored_frame_counter = frame_counter; update_needed = true; - tr_debug("Stored updated frame counter: index %i value %"PRIu32"", i, curr_frame_counter); + tr_debug("Stored updated frame counter: index %i value %"PRIu32"", i, frame_counter); } } else { // For new or modified network keys, stores the frame counter value entry->frame_counters.counter[i].set = true; memcpy(entry->frame_counters.counter[i].gtk, entry->nw_key[i].gtk, GTK_LEN); entry->frame_counters.counter[i].frame_counter = curr_frame_counter; + entry->frame_counters.counter[i].stored_frame_counter = curr_frame_counter; update_needed = true; tr_debug("Stored new frame counter: index %i value %"PRIu32"", i, curr_frame_counter); } diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index 3b3ae88c7b85..15b8dbc32bab 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -102,7 +102,8 @@ typedef struct { // Frame counter data typedef struct { uint8_t gtk[GTK_LEN]; /**< GTK of the frame counter */ - uint32_t frame_counter; /**< Frame counter */ + uint32_t frame_counter; /**< Current frame counter */ + uint32_t stored_frame_counter; /**< Stored Frame counter */ bool set : 1; /**< Value has been set */ } frame_counter_t; From 45f851997f67e6ab6a3eb87c6acf4d847d2e083b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Fri, 22 Nov 2019 09:16:25 +0200 Subject: [PATCH 09/88] On stop (ifdown) stores frame counters regardless of threshold --- source/6LoWPAN/ws/ws_pae_controller.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 383af27ba946..14f0aeca8d2d 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -109,6 +109,7 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_ static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key); static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index); static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name); +static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr, pae_controller_t *controller, bool use_threshold); static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index); static void ws_pae_controller_data_init(pae_controller_t *controller); static void ws_pae_controller_frame_counter_read(pae_controller_t *controller); @@ -477,8 +478,15 @@ void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface return; } + /* Stores frame counters if incremented by threshold and removes network keys from PAE + controller and MAC */ + ws_pae_controller_frame_counter_store_and_nw_keys_remove(interface_ptr, controller, true); +} + +static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr, pae_controller_t *controller, bool use_threshold) +{ /* Checks if frame counters needs to be stored when keys are removed */ - ws_pae_controller_frame_counter_store(controller, true); + ws_pae_controller_frame_counter_store(controller, use_threshold); tr_info("NW keys remove"); @@ -703,8 +711,8 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr) return -1; } - // Removes network keys from PAE controller and MAC - ws_pae_controller_nw_keys_remove(interface_ptr); + // Stores frame counters and removes network keys from PAE controller and MAC + ws_pae_controller_frame_counter_store_and_nw_keys_remove(interface_ptr, controller, false); // If PAE has been initialized, deletes it if (controller->pae_delete) { From 96ffe9274462f4a05ad95168debd204faf32723a Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 28 Nov 2019 11:39:24 +0200 Subject: [PATCH 10/88] Adaptation layer to support multiple simultaneous unicast transmissions (#2243) * Adaptation layer to support multiple simultaneous unicast transmissions * Prevent all frames when fragmenter active --- source/6LoWPAN/adaptation_interface.c | 135 ++++++++++++------ .../test_adaptation_interface.c | 12 +- 2 files changed, 95 insertions(+), 52 deletions(-) diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 0758ed4d1230..73ca406e541a 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -89,8 +89,8 @@ typedef struct { fragmenter_tx_list_t indirect_tx_queue; uint8_t *fragment_indirect_tx_buffer; //Used for write fragmentation header uint16_t mtu_size; - fragmenter_tx_entry_t active_unicast_tx_buf; //Current active direct unicast tx process fragmenter_tx_entry_t active_broadcast_tx_buf; //Current active direct broadcast tx process + fragmenter_tx_list_t activeUnicastList; //Unicast packets waiting data confirmation from MAC buffer_list_t directTxQueue; //Waiting free tx process uint16_t directTxQueue_size; uint16_t indirect_big_packet_threshold; @@ -110,7 +110,7 @@ static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t inter /* Interface direct message pending queue functions */ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf); -static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur); +static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr); /* Data direction and message length validation */ static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *mle_entry); @@ -126,7 +126,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf /* Tx confirmation local functions */ static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf); -static fragmenter_tx_entry_t *lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue); +static fragmenter_tx_entry_t *lowpan_listed_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue); static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event); static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status); static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr); @@ -138,6 +138,8 @@ static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interf static fragmenter_tx_entry_t *lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); +static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buffer_t *buf); + static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm) { switch (confirm->status) { @@ -221,18 +223,14 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); } -static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur) +static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr) { - /* Currently this function is called only when data confirm is received for previously sent packet. - * Data confirm has freed the corresponding "active buffer" and this function will look for new buffer to be set as active buffer. - */ + // Currently this function is called only when data confirm is received for previously sent packet. + if (!interface_ptr->directTxQueue_size) { + return NULL; + } ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) { - bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); - //Check that we not trig second active fragmentation process - if (fragmented_needed && interface_ptr->fragmenter_active) { - tr_debug("Do not trig Second active fragmentation"); - } else if ((buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_unicast_tx_buf.buf) - || (!buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_broadcast_tx_buf.buf)) { + if (lowpan_buffer_tx_allowed(interface_ptr, buf)) { ns_list_remove(&interface_ptr->directTxQueue, buf); interface_ptr->directTxQueue_size--; protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); @@ -292,7 +290,7 @@ static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf) -static fragmenter_tx_entry_t *lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue) +static fragmenter_tx_entry_t *lowpan_listed_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue) { ns_list_foreach(fragmenter_tx_entry_t, entry, indirect_tx_queue) { if (entry->buf->seq == handle) { @@ -310,9 +308,9 @@ static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *int uint8_t handle; while (!valid_info) { handle = interface_ptr->msduHandle++; - if (!lowpan_active_tx_handle_verify(handle, interface_ptr->active_unicast_tx_buf.buf) + if (!lowpan_listed_tx_handle_verify(handle, &interface_ptr->activeUnicastList) && !lowpan_active_tx_handle_verify(handle, interface_ptr->active_broadcast_tx_buf.buf) - && !lowpan_indirect_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) { + && !lowpan_listed_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) { valid_info = true; } } @@ -320,7 +318,7 @@ static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *int } -static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list, fragmenter_tx_entry_t *entry) +static void lowpan_list_entry_free(fragmenter_tx_list_t *list, fragmenter_tx_entry_t *entry) { ns_list_remove(list, entry); if (entry->buf) { @@ -330,11 +328,11 @@ static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list, fragmenter_tx ns_dyn_mem_free(entry); } -static void lowpan_indirect_queue_free(fragmenter_tx_list_t *list) +static void lowpan_list_free(fragmenter_tx_list_t *list) { while (!ns_list_is_empty(list)) { fragmenter_tx_entry_t *entry = ns_list_get_first(list); - lowpan_indirect_entry_free(list, entry); + lowpan_list_entry_free(list, entry); } } @@ -365,6 +363,7 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si ns_list_init(&interface_ptr->indirect_tx_queue); ns_list_init(&interface_ptr->directTxQueue); + ns_list_init(&interface_ptr->activeUnicastList); ns_list_add_to_end(&fragmenter_interface_list, interface_ptr); @@ -389,11 +388,11 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id) ns_list_remove(&fragmenter_interface_list, interface_ptr); //free active tx process - lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); + lowpan_list_free(&interface_ptr->activeUnicastList); lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Free Indirect entry - lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); + lowpan_list_free(&interface_ptr->indirect_tx_queue); buffer_free_list(&interface_ptr->directTxQueue); @@ -414,13 +413,13 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) } //free active tx process - lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); + lowpan_list_free(&interface_ptr->activeUnicastList); lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Clean fragmented message flag interface_ptr->fragmenter_active = false; //Free Indirect entry - lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); + lowpan_list_free(&interface_ptr->indirect_tx_queue); buffer_free_list(&interface_ptr->directTxQueue); @@ -588,10 +587,15 @@ static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry static fragmenter_tx_entry_t *lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast) { + // For broadcast, the active TX queue is only 1 entry. For unicast, using a list. fragmenter_tx_entry_t *tx_entry; if (!indirect) { if (is_unicast) { - tx_entry = &interface_ptr->active_unicast_tx_buf; + tx_entry = lowpan_indirect_entry_allocate(0); + if (!tx_entry) { + return NULL; + } + ns_list_add_to_end(&interface_ptr->activeUnicastList, tx_entry); } else { tx_entry = &interface_ptr->active_broadcast_tx_buf; } @@ -936,6 +940,40 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf } } +static bool lowpan_adaptation_is_destination_tx_active(fragmenter_tx_list_t *list, buffer_t *buf) +{ + ns_list_foreach(fragmenter_tx_entry_t, entry, list) { + if (entry->buf) { + if (!memcmp(&entry->buf->dst_sa.address[2], &buf->dst_sa.address[2], 8)) { + return true; + } + } + } + return false; +} + +static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buffer_t *buf) +{ + bool is_unicast = buf->link_specific.ieee802_15_4.requestAck; + // Indirect allowed always + if (buf->link_specific.ieee802_15_4.indirectTxProcess) { + return true; + } + // Do not accept any other TX when fragmented TX active. Prevents other frames to be sent in between two fragments. + if (interface_ptr->fragmenter_active) { + return false; + } + // Do not accept more than one active broadcast TX + if (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf) { + return false; + } + // Do not accept more than one active unicast TX per destination + if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) { + return false; + } + return true; +} + int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf) { bool is_room_for_new_message; @@ -956,11 +994,10 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); bool is_unicast = buf->link_specific.ieee802_15_4.requestAck; bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess; - if (!indirect) { - if (((is_unicast && interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf)) || (fragmented_needed && interface_ptr->fragmenter_active)) { - lowpan_adaptation_tx_queue_write(interface_ptr, buf); - return 0; //Return here - } + + if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) { + lowpan_adaptation_tx_queue_write(interface_ptr, buf); + return 0; } //Allocate Handle @@ -1107,10 +1144,14 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr) static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event) { buffer_t *buf = tx_ptr->buf; + tx_ptr->buf = NULL; if (buf->link_specific.ieee802_15_4.indirectTxProcess) { //release from list and free entry - lowpan_indirect_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr); + lowpan_list_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr); + } else if (buf->link_specific.ieee802_15_4.requestAck) { + ns_list_remove(&interface_ptr->activeUnicastList, tx_ptr); + ns_dyn_mem_free(tx_ptr); } socket_tx_buffer_event_and_free(buf, socket_event); @@ -1131,18 +1172,19 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c //Check first fragmenter_tx_entry_t *tx_ptr; bool active_direct_confirm; - bool is_unicast = true; - - if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_unicast_tx_buf.buf)) { - active_direct_confirm = true; - tx_ptr = &interface_ptr->active_unicast_tx_buf; - } else if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_broadcast_tx_buf.buf)) { + if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_broadcast_tx_buf.buf)) { active_direct_confirm = true; tx_ptr = &interface_ptr->active_broadcast_tx_buf; - is_unicast = false; } else { - active_direct_confirm = false; - tx_ptr = lowpan_indirect_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue); + tx_ptr = lowpan_listed_tx_handle_verify(confirm->msduHandle, &interface_ptr->activeUnicastList); + if (tx_ptr) { + active_direct_confirm = true; + } else { + tx_ptr = lowpan_listed_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue); + if (tx_ptr) { + active_direct_confirm = false; + } + } } if (!tx_ptr) { @@ -1232,14 +1274,15 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c break; } - - if ((is_unicast && !interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && !interface_ptr->active_broadcast_tx_buf.buf)) { - //Read Buffer and trig next direct request - lowpan_adaptation_interface_tx(cur, lowpan_adaptation_tx_queue_read(interface_ptr, cur)); + // When confirmation is for direct transmission, push all allowed buffers to MAC + if (active_direct_confirm == true) { + buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr); + while (buf_from_queue) { + lowpan_adaptation_interface_tx(cur, buf_from_queue); + buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr); + } } - return 0; - } static bool mac_data_is_broadcast_addr(const sockaddr_t *addr) @@ -1332,7 +1375,7 @@ bool lowpan_adaptation_tx_active(int8_t interface_id) { fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); - if (!interface_ptr || (!interface_ptr->active_unicast_tx_buf.buf && !interface_ptr->active_broadcast_tx_buf.buf)) { + if (!interface_ptr || (!ns_list_count(&interface_ptr->activeUnicastList) && !interface_ptr->active_broadcast_tx_buf.buf)) { return false; } return true; diff --git a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c index 43375c09525c..0887389d0806 100644 --- a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c +++ b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c @@ -534,7 +534,7 @@ bool test_lowpan_adaptation_interface_tx() } test_buf->link_specific.ieee802_15_4.useDefaultPanId = true; - test_buf->link_specific.ieee802_15_4.requestAck = true; + test_buf->link_specific.ieee802_15_4.requestAck = false; if (0 != lowpan_adaptation_interface_tx(&entry, test_buf)) { return false; @@ -546,7 +546,7 @@ bool test_lowpan_adaptation_interface_tx() test_buf2->dst_sa.addr_type = ADDR_802_15_4_SHORT; test_buf2->link_specific.ieee802_15_4.useDefaultPanId = true; - test_buf2->link_specific.ieee802_15_4.requestAck = true; + test_buf2->link_specific.ieee802_15_4.requestAck = false; test_buf2->link_specific.ieee802_15_4.indirectTxProcess = false; test_buf2->link_specific.ieee802_15_4.rf_channel_switch = true; test_buf2->link_specific.ieee802_15_4.selected_channel = 12; @@ -562,7 +562,7 @@ bool test_lowpan_adaptation_interface_tx() test_buf3->dst_sa.addr_type = ADDR_802_15_4_SHORT; - test_buf3->link_specific.ieee802_15_4.requestAck = true; + test_buf3->link_specific.ieee802_15_4.requestAck = false; test_buf3->buf_end = 90; test_buf3->priority = QOS_HIGH; @@ -791,7 +791,7 @@ bool test_lowpan_adaptation_interface_tx_confirm() buffer_dyn_stub.buffer_ptr = test_buf; test_buf->buf_ptr = 10; test_buf->buf_end = 70; - test_buf->link_specific.ieee802_15_4.requestAck = true; + test_buf->link_specific.ieee802_15_4.requestAck = false; test_buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT; test_buf->link_specific.ieee802_15_4.rf_channel_switch = true; @@ -802,7 +802,7 @@ bool test_lowpan_adaptation_interface_tx_confirm() test_buf2->dst_sa.addr_type = ADDR_802_15_4_SHORT; test_buf2->buf_ptr = 10; test_buf2->buf_end = 70; - test_buf2->link_specific.ieee802_15_4.requestAck = true; + test_buf2->link_specific.ieee802_15_4.requestAck = false; test_buf2->link_specific.ieee802_15_4.rf_channel_switch = true; test_buf2->link_specific.ieee802_15_4.selected_channel = 12; @@ -811,7 +811,7 @@ bool test_lowpan_adaptation_interface_tx_confirm() test_buf3->dst_sa.addr_type = ADDR_802_15_4_SHORT; test_buf3->buf_ptr = 10; test_buf3->buf_end = 70; - test_buf3->link_specific.ieee802_15_4.requestAck = true; + test_buf3->link_specific.ieee802_15_4.requestAck = false; test_buf3->link_specific.ieee802_15_4.indirectTxProcess = true; entry.mac_api = &api; From 3441594157d53df3f425019940034d2922c9e23b Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 20 Nov 2019 14:25:17 +0200 Subject: [PATCH 11/88] RPL parent candidate list update Added new API for RPL to ask instance candidate list sizeand size. Added API for remove worst parent candidate from list if user detect too much usage for replace. Replaced candidate must be proped or otherwise new candidate is dropped. Extend Objection function point for validate is new candidate enough good for add. WS_RPL_MIN_HOP_RANK_INCREASE from 196 to 160. This will reduce a case that device is not switching too aggressive to 1 hop shorter parent. Update Worts candidate select function for compare path cost and smarter dio age definition. Change-Id: I67150ab4eae96c90fbded9ff1a9c9084bdf97eae --- source/6LoWPAN/ws/ws_bootstrap.c | 97 ++++++++++++------- source/6LoWPAN/ws/ws_config.h | 2 +- source/RPL/rpl_control.c | 96 ++++++++++++++++-- source/RPL/rpl_control.h | 15 ++- source/RPL/rpl_mrhof.c | 14 +++ source/RPL/rpl_objective.h | 5 +- source/RPL/rpl_of0.c | 9 ++ source/RPL/rpl_structures.h | 6 +- source/RPL/rpl_upward.c | 60 ++++++++++-- source/RPL/rpl_upward.h | 5 +- .../unittest/stub/rpl_control_stub.c | 15 +++ .../nanostack/unittest/stub/rpl_upward_stub.c | 12 ++- 12 files changed, 272 insertions(+), 64 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index a9e9037bba3b..d598ccb608b7 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -97,7 +97,6 @@ static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t * static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor); static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr); static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data); -static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface); static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); @@ -321,12 +320,16 @@ static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighb } } -static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor) +static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor, bool nud_process) { //Send NS uint8_t ll_target[16]; ws_bootsrap_create_ll_address(ll_target, neighbor->mac64); - tr_info("NUD generate NS %u", neighbor->index); + if (nud_process) { + tr_info("NUD generate NS %u", neighbor->index); + } else { + tr_info("Probe generate NS %u", neighbor->index); + } buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); if (buffer) { protocol_push(buffer); @@ -368,7 +371,7 @@ void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks) } else { //Random TX wait period is over - entry->wait_response = ws_nud_message_build(cur, entry->neighbor_info); + entry->wait_response = ws_nud_message_build(cur, entry->neighbor_info, entry->nud_process); if (!entry->wait_response) { if (entry->nud_process && entry->retry_count < 2) { entry->timer = randLIB_get_random_in_range(1, 900); @@ -1591,25 +1594,6 @@ static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_en return true; } -static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface) -{ - uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false); - //TODO check bootstarap state for review - //if we have enough candidates at list do not accept new multicast neighbours - if (parent_candidate_size > interface->ws_info->rpl_parent_candidate_max) { - return false; - } - - parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true); - //If we have already enough parent selected Candidates count is bigger than configured - if (parent_candidate_size >= interface->ws_info->rpl_selected_parent_max) { - return false; - } - - return true; -} - - static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { @@ -1647,7 +1631,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, } uint8_t ll_address[16]; - + bool nud_proces = false; if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT) { ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); @@ -1668,6 +1652,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, activate_nud = true; } } + nud_proces = activate_nud; } else if (etx_entry->etx_samples < WS_NEIGBOR_ETX_SAMPLE_MAX) { //Take Random number for trig a prope. //ETX Sample 0: random 1-8 @@ -1679,7 +1664,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, } else { ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); - if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) { + if (!rpl_control_probe_parent_candidate(cur, ll_address)) { return false; } @@ -1712,10 +1697,8 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, ws_neighbor->accelerated_etx_probe = false; entry->timer = 1; } + entry->nud_process = nud_proces; - if (etx_entry->etx_samples >= WS_NEIGBOR_ETX_SAMPLE_MAX) { - entry->nud_process = true; - } return true; } @@ -2150,7 +2133,7 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t } } -static bool ws_rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle) +static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank) { protocol_interface_info_entry_t *cur = handle; @@ -2158,26 +2141,62 @@ static bool ws_rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handl return false; } + if (blacklist_reject(ll_parent_address)) { + // Rejected by blacklist + return false; + } + + uint8_t replacing[16]; uint8_t mac64[8]; - memcpy(mac64, ll_parent_address + 8, 8); - mac64[0] ^= 2; + bool replace_ok = false; + bool create_ok = false; llc_neighbour_req_t neigh_buffer; + if (rpl_control_candidate_list_size(cur, instance) < cur->ws_info->rpl_parent_candidate_max) { + //Not reach max value yet accept then all go to create neigh table + goto neigh_create; + } + + + if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) { + return false; + } + + // if not yet probed, return false + memcpy(mac64, replacing + 8, 8); + mac64[0] ^= 2; + if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { - return true; + //Verify that we have proped min 1 time + etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, neigh_buffer.neighbor->index); + if (etx_entry && etx_entry->etx_samples == 0) { + return false; + } } - if (!ws_rpl_dio_new_parent_accept(cur)) { + // Accept now only better one's when max candidates slected and max candidate list size is reached + if (!rpl_possible_better_candidate(cur, instance, replacing, candidate_rank)) { return false; } + //TODO if replacing has poor ETX, put it in blacklist as "poor ETX" to prevent reselection + //Mark That We can try remove replaced link + replace_ok = true; - //Discover Multicast temporary entry +neigh_create: + + memcpy(mac64, ll_parent_address + 8, 8); + mac64[0] ^= 2; + if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { + create_ok = true; + goto neigh_create_ok; + } + //Discover Multicast temporary entry ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); if (!entry) { return false; } //Create entry - bool create_ok = ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, true); + create_ok = ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, true); if (create_ok) { ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; //Copy fhss temporary data @@ -2188,7 +2207,13 @@ static bool ws_rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handl } ws_llc_free_multicast_temp_entry(cur, entry); +neigh_create_ok: + if (create_ok && replace_ok) { + //Try remove here when accepted new better one possible + tr_debug("Remove %s by %s", trace_ipv6(replacing), trace_ipv6(ll_parent_address)); + rpl_control_neighbor_delete_from_instance(cur, instance, replacing); + } return create_ok; } @@ -2200,7 +2225,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) addr_add_router_groups(cur); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback_t, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback, cur); // If i am router I Do this rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); rpl_control_request_parent_link_confirmation(true); diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 9ff0007021bd..2504fb910f3e 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -31,7 +31,7 @@ #define WS_RPL_DIO_DOUBLING 2 #define WS_RPL_DIO_REDUNDANCY 0 -#define WS_RPL_MIN_HOP_RANK_INCREASE 196 +#define WS_RPL_MIN_HOP_RANK_INCREASE 160 #define WS_RPL_MAX_HOP_RANK_INCREASE 2048 #define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128 diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index af5db008159b..697ba7b6ca53 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -247,6 +247,46 @@ bool rpl_control_is_dodag_parent_candidate(protocol_interface_info_entry_t *inte return false; } +uint16_t rpl_control_candidate_list_size(protocol_interface_info_entry_t *interface, rpl_instance_t *rpl_instance) +{ + if (!interface->rpl_domain) { + return 0; + } + + return rpl_instance_address_candidate_count(rpl_instance, false); + +} + + +bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) +{ + if (!interface->rpl_domain) { + return false; + } + // go through instances and parents and check if they match the address. + ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) { + if (rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id)) { + return true; + } + } + return false; +} + +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, rpl_instance_t *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank) +{ + if (!interface->rpl_domain) { + return false; + } + + rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(rpl_instance, ll_addr, interface->id); + if (!neighbour) { + return false; + } + + return rpl_instance_possible_better_candidate(rpl_instance, neighbour, candidate_rank); + +} + uint16_t rpl_control_parent_candidate_list_size(protocol_interface_info_entry_t *interface, bool parent_list) { @@ -266,6 +306,13 @@ uint16_t rpl_control_parent_candidate_list_size(protocol_interface_info_entry_t return parent_list_size; } +void rpl_control_neighbor_delete_from_instance(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, const uint8_t ll_addr[16]) +{ + rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id); + if (neighbour) { + rpl_delete_neighbour(instance, neighbour); + } +} void rpl_control_neighbor_delete(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) { @@ -274,14 +321,26 @@ void rpl_control_neighbor_delete(protocol_interface_info_entry_t *interface, con } // go through instances and delete address. ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) { + rpl_control_neighbor_delete_from_instance(interface, instance, ll_addr); + } +} - rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id); - if (neighbour) { - rpl_delete_neighbour(instance, neighbour); - } +bool rpl_control_find_worst_neighbor(protocol_interface_info_entry_t *interface, rpl_instance_t *rpl_instance, uint8_t ll_addr[static 16]) +{ + if (!interface->rpl_domain) { + return false; + } + + rpl_neighbour_t *neighbour = rpl_lookup_last_candidate_from_list(rpl_instance); + if (neighbour) { + memcpy(ll_addr, rpl_neighbour_ll_address(neighbour), 16); + return true; } + + return false; } + /* Address changes need to trigger DAO target re-evaluation */ static void rpl_control_addr_notifier(struct protocol_interface_info_entry *interface, const if_address_entry_t *addr, if_address_callback_t reason) { @@ -1015,7 +1074,7 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r const rpl_dodag_conf_t *conf = rpl_dodag_get_config(dodag); if (!conf) { /* TODO - rate limit DIS? */ - if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle)) { + if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle, instance, rank)) { goto invalid_parent; } rpl_control_transmit_dis(domain, cur, RPL_SOLINFO_PRED_DODAGID | RPL_SOLINFO_PRED_INSTANCEID, instance_id, dodagid, 0, buf->src_sa.address); @@ -1049,15 +1108,21 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r /* Now we create the neighbour, if we don't already have a record */ if (!neighbour) { + + if (domain->new_parent_add) { + + if (!domain->new_parent_add(buf->src_sa.address, domain->cb_handle, instance, rank)) { + goto invalid_parent; + } + } + neighbour = rpl_create_neighbour(version, buf->src_sa.address, cur->id, g_mop_prf, dtsn); //Call Here new parent create if (!neighbour) { goto invalid_parent; } - if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle)) { - goto invalid_parent; - } + } @@ -1776,12 +1841,25 @@ static void rpl_domain_print(const rpl_domain_t *domain, route_print_fn_t *print void rpl_control_print(route_print_fn_t *print_fn) { - print_fn("RPL memory usage %zu", rpl_alloc_total); + unsigned t = protocol_core_monotonic_time % 10; + unsigned s_full = protocol_core_monotonic_time / 10; + unsigned m = s_full / 60; + unsigned s = s_full % 60; + unsigned h = m / 60; + m %= 60; + print_fn("Time %02u:%02u:%02u.%u (%u.%u)", h, m, s, t, s_full, t); + // %zu doesn't work on some Mbed toolchains + print_fn("RPL memory usage %" PRIu32, (uint32_t) rpl_alloc_total); ns_list_foreach(rpl_domain_t, domain, &rpl_domains) { rpl_domain_print(domain, print_fn); } } +uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain) +{ + return rpl_policy_mrhof_parent_set_size(domain); +} + #ifdef RPL_STRUCTURES_H_ #error "rpl_structures.h should not be included by rpl_control.c" #endif diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 7569bac94490..63967209e099 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -42,7 +42,8 @@ typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local); -typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle); +typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank); + typedef struct rpl_domain { NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; @@ -146,15 +147,21 @@ void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); void rpl_control_free_domain_instances_from_interface(struct protocol_interface_info_entry *cur); -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle); +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); void rpl_control_unpublish_address(rpl_domain_t *domain, const uint8_t addr[16]); bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); bool rpl_control_is_dodag_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint16_t candidate_cmp_limiter); -uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list); +bool rpl_control_probe_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank); +uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list); +uint16_t rpl_control_candidate_list_size(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance); void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); +void rpl_control_neighbor_delete_from_instance(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16]); +bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, uint8_t ll_addr[16]); + /* Parent link confirmation API extension */ void rpl_control_request_parent_link_confirmation(bool requested); void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count); @@ -176,6 +183,7 @@ bool rpl_control_read_dodag_info(const struct rpl_instance *instance, struct rpl const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance *instance); const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global); uint16_t rpl_control_current_rank(const struct rpl_instance *instance); +uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain); #else /* HAVE_RPL */ @@ -185,6 +193,7 @@ uint16_t rpl_control_current_rank(const struct rpl_instance *instance); #define rpl_control_free_domain_instances_from_interface(cur) ((void) 0) #define rpl_control_register_address(interface, addr) ((void) 0) #define rpl_control_address_register_done(interface, ll_addr, status) ((void) 0) +#define rpl_policy_mrhof_parent_set_size_get(domain) (0) #endif /* HAVE_RPL */ diff --git a/source/RPL/rpl_mrhof.c b/source/RPL/rpl_mrhof.c index bfff5aa00046..9581f595a08b 100644 --- a/source/RPL/rpl_mrhof.c +++ b/source/RPL/rpl_mrhof.c @@ -45,12 +45,14 @@ static void rpl_mrhof_parent_selection(rpl_instance_t *instance); static uint16_t rpl_mrhof_path_cost_through_neighbour(const rpl_neighbour_t *neighbour); static bool rpl_mrhof_neighbour_acceptable(const rpl_instance_t *instance, const rpl_neighbour_t *neighbour); +static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank); static rpl_objective_t rpl_mrhof = { .ocp = RPL_OCP_MRHOF, .parent_selection = rpl_mrhof_parent_selection, .path_cost = rpl_mrhof_path_cost_through_neighbour, .neighbour_acceptable = rpl_mrhof_neighbour_acceptable, + .possible_better_candidate = rpl_mrhof_possible_better_candidate, }; typedef struct rpl_of0_params { @@ -94,6 +96,18 @@ static bool rpl_mrhof_neighbour_acceptable(const rpl_instance_t *instance, const return rpl_mrhof_link_metric_to_neighbour(neighbour) <= rpl_policy_mrhof_max_link_metric(instance->domain); } +static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank) +{ + uint16_t existing_path = rpl_mrhof_path_cost_through_neighbour(existing); + // Optimistically assume we could get a perfect link to this new person + // But add hysteresis to avoid switching unless potentially worthwhile + // (Compare rpl_mrhof_etx which assumes poor for unknown as a sort of hysteresis) + // Think: could actually use rpl_mrhof_etx here to get an existing ETX estimate + // (except that gives infinite if no current link, would want a variant that checks + // blacklist records for remembered poor ETX) + uint16_t potential_path_with_hysteresis = rpl_rank_add(rank, 128 + rpl_policy_mrhof_parent_switch_threshold(instance->domain)); + return potential_path_with_hysteresis <= existing_path; +} /* Given a preferred parent, we are only permitted to stretch our above the * path cost through that parent by a certain (policy) amount to accommodate a diff --git a/source/RPL/rpl_objective.h b/source/RPL/rpl_objective.h index 67c35fd7c802..fa36b0ce4cd3 100644 --- a/source/RPL/rpl_objective.h +++ b/source/RPL/rpl_objective.h @@ -28,9 +28,12 @@ typedef struct rpl_objective { uint16_t ocp; /* Run the parent selection algorithm - see rpl_of0.c for detailed info */ void (*parent_selection)(struct rpl_instance *); - /* Return the path cost of a neighbour (for debug prints only) */ + /* Return the path cost of a neighbour */ uint16_t (*path_cost)(const struct rpl_neighbour *); bool (*neighbour_acceptable)(const struct rpl_instance *, const struct rpl_neighbour *); + /* Could someone with specified rank be a significantly better candidate than the existing one? */ + /* (In future, this API could be extended to pass a metric pointer as well as rank) */ + bool (*possible_better_candidate)(const struct rpl_instance *, const struct rpl_neighbour *existing, uint16_t rank); ns_list_link_t link; } rpl_objective_t; diff --git a/source/RPL/rpl_of0.c b/source/RPL/rpl_of0.c index aa6927c1f169..66a237c76022 100644 --- a/source/RPL/rpl_of0.c +++ b/source/RPL/rpl_of0.c @@ -42,12 +42,14 @@ static void rpl_of0_parent_selection(rpl_instance_t *instance); static uint16_t rpl_of0_rank_through_neighbour(const rpl_neighbour_t *neighbour); static bool rpl_of0_neighbour_acceptable(const rpl_instance_t *instance, const rpl_neighbour_t *neighbour); +static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank); static rpl_objective_t rpl_of0 = { .ocp = RPL_OCP_OF0, .parent_selection = rpl_of0_parent_selection, .path_cost = rpl_of0_rank_through_neighbour, .neighbour_acceptable = rpl_of0_neighbour_acceptable, + .possible_better_candidate = rpl_of0_possible_better_candidate, }; #define DEFAULT_STEP_OF_RANK 3 @@ -115,6 +117,13 @@ static uint16_t rpl_of0_rank_through_neighbour(const rpl_neighbour_t *neighbour) return rpl_rank_add(neighbour->rank, rpl_of0_rank_increase(neighbour)); } +static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank) +{ + uint16_t existing_path = rpl_of0_rank_through_neighbour(existing); + uint16_t potential_path_with_hysteresis = rpl_rank_add(rank, 2 * rpl_policy_of0_rank_factor(instance->domain) * existing->dodag_version->dodag->config.min_hop_rank_increase); + return potential_path_with_hysteresis <= existing_path; +} + /* Given a preferred parent, we are only permitted to stretch our above the * path cost through that parent by a certain (policy) amount to accommodate a * bigger parent set. diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 60e815afa3d9..71c286f274e0 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -32,10 +32,6 @@ struct rpl_objective; /* Descriptor for a RPL neighbour within a DODAG - * - * The neighbour is normally associated with a DODAG Version, but may not be, - * if the version has been retired, and we haven't since heard from that - * neighbour. In that case dodag_version is NULL. * * Note that global address is only needed with downward routes, but I don't * think it's worth optimising for an "upward-only" build. (Unless to be a RPL @@ -45,7 +41,7 @@ struct rpl_objective; * first in the instance candidate_neighbour list, in order of preference. */ struct rpl_neighbour { - rpl_dodag_version_t *dodag_version; // Back pointer to DODAG Version (may be NULL, if not dodag_parent) + rpl_dodag_version_t *dodag_version; // Back pointer to DODAG Version uint8_t ll_address[16]; // Link-local address (source of DIO) uint8_t global_address[16]; // Global address (from DIO RIO) bool dodag_parent: 1; // This is a DODAG parent (if true, dodag_version may not be NULL) diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 6e0a04a16a2d..d905a6dc808e 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -74,6 +74,8 @@ static NS_LIST_DEFINE(rpl_candidate_neighbour_set, rpl_neighbour_t, candidate_ne static void rpl_instance_remove_parents(rpl_instance_t *instance); static void rpl_instance_remove_system_routes_through_parent(rpl_instance_t *instance, rpl_neighbour_t *parent); static void rpl_dodag_update_system_route(rpl_dodag_t *dodag, rpl_dio_route_t *route); +static rpl_neighbour_t *rpl_instance_choose_worst_neighbour(const rpl_instance_t *instance); +static uint32_t rpl_dio_imax_time_calculate(uint16_t Imax, uint16_t fixed_point); /* Rank comparison, and DAGRank(rank) */ uint16_t nrpl_dag_rank(const rpl_dodag_t *dodag, uint16_t rank) @@ -283,6 +285,16 @@ rpl_neighbour_t *rpl_instance_preferred_parent(const rpl_instance_t *instance) return neighbour; } +uint16_t rpl_instance_candidate_rank(const rpl_neighbour_t *candidate) +{ + return candidate->rank; +} + +bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank) +{ + return instance->of->possible_better_candidate(instance, replacing, candidate_rank); +} + /* If we're a member of a DODAG Version matching the predicate in this instance, * return it. Mainly used for handling DODAG Information Solicitations. */ @@ -390,6 +402,15 @@ rpl_neighbour_t *rpl_lookup_neighbour_by_ll_address(const rpl_instance_t *instan return NULL; } +rpl_neighbour_t *rpl_lookup_last_candidate_from_list(const rpl_instance_t *instance) +{ + rpl_neighbour_t *neighbour = rpl_instance_choose_worst_neighbour(instance); + if (neighbour && neighbour->considered && !neighbour->dodag_parent) { + return neighbour; + } + return NULL; +} + rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *version, const uint8_t *addr, int8_t if_id, uint8_t g_mop_prf, uint8_t dtsn) { /* Should gate higher-rank neighbours here - ignore higher-rank neighbours @@ -1164,10 +1185,20 @@ static rpl_neighbour_t *rpl_instance_choose_worst_neighbour(const rpl_instance_t { rpl_neighbour_t *worst = NULL; bool worst_acceptable = false; + bool worst_old = false; /* Parents will be first - loop backwards so we take non-parents first */ ns_list_foreach_reverse(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { bool acceptable = instance->of->neighbour_acceptable(instance, neighbour); + bool old; + if (!neighbour->dodag_version) { + old = true; + } else { + uint32_t age = protocol_core_monotonic_time - neighbour->dio_timestamp; + uint32_t age_threshold = rpl_dio_imax_time_calculate(neighbour->dodag_version->dodag->dio_timer_params.Imax, + rpl_policy_dio_validity_period(instance->domain)); + old = age > age_threshold; + } if (!worst) { goto new_worst; } @@ -1177,6 +1208,13 @@ static rpl_neighbour_t *rpl_instance_choose_worst_neighbour(const rpl_instance_t break; } + /* Prefer neighbours with DODAG version */ + if (neighbour->dodag_version && !worst->dodag_version) { + continue; + } else if (!neighbour->dodag_version && worst->dodag_version) { + goto new_worst; + } + /* Prefer to purge "unacceptable" neighbours according to OF */ if (acceptable && !worst_acceptable) { continue; @@ -1184,18 +1222,24 @@ static rpl_neighbour_t *rpl_instance_choose_worst_neighbour(const rpl_instance_t goto new_worst; } - /* Prefer to purge least-recently-heard-from */ - uint32_t neighbour_age = protocol_core_monotonic_time - neighbour->dio_timestamp; - uint32_t worst_age = protocol_core_monotonic_time - worst->dio_timestamp; - if (neighbour_age <= worst_age) { + /* Prefer to purge old neighbours */ + if (old && !worst_old) { continue; - } else { + } else if (!old && worst_old) { goto new_worst; } + /* Tiebreak by path cost, assuming we have dodag_version */ + if (neighbour->dodag_version && instance->of) { + /* worst must also have version to reach this tiebreak */ + if (instance->of->path_cost(neighbour) <= instance->of->path_cost(worst)) { + continue; + } + } new_worst: worst = neighbour; worst_acceptable = acceptable; + worst_old = old; } return worst; @@ -1226,6 +1270,7 @@ bool rpl_instance_purge(rpl_instance_t *instance) */ rpl_neighbour_t *neighbour = rpl_instance_choose_worst_neighbour(instance); if (neighbour && neighbour->considered && !neighbour->dodag_parent && neighbour->dao_path_control == 0) { + tr_debug("Candidate Purge: Remove %s", trace_ipv6(neighbour->ll_address)); rpl_delete_neighbour(instance, neighbour); return true; } @@ -1390,6 +1435,7 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) ns_list_foreach_safe(rpl_neighbour_t, n, &instance->candidate_neighbours) { //Remove a Parent candidates which are not heared a long time ago and not slected ones if (!n->dodag_parent && (rpl_aged_lifetime(rpl_default_lifetime(n->dodag_version->dodag), n->dio_timestamp) == 0)) { + tr_debug("Candidate timeout: Remove %s", trace_ipv6(n->ll_address)); rpl_delete_neighbour(instance, n); continue; } @@ -1481,6 +1527,7 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) continue; } if (!instance->of->neighbour_acceptable(instance, n)) { + tr_debug("Candidate not acceptable: Remove %s", trace_ipv6(n->ll_address)); rpl_delete_neighbour(instance, n); } } @@ -1701,7 +1748,7 @@ bool rpl_instance_address_is_candidate(rpl_instance_t *instance, const uint8_t * return false; } -uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents) +uint16_t rpl_instance_address_candidate_count(const rpl_instance_t *instance, bool selected_parents) { uint16_t parent_list = 0; @@ -1719,7 +1766,6 @@ uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool sel return parent_list; } - void rpl_instance_neighbor_delete(rpl_instance_t *instance, const uint8_t *ipv6_addr) { ns_list_foreach_safe(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index cd920606b38e..4ebc51d1f7ff 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -70,6 +70,7 @@ bool rpl_instance_am_root(const rpl_instance_t *instance); uint8_t rpl_instance_mop(const rpl_instance_t *instance); rpl_dodag_version_t *rpl_instance_current_dodag_version(const rpl_instance_t *instance); rpl_neighbour_t *rpl_instance_preferred_parent(const rpl_instance_t *instance); +bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank); rpl_dodag_version_t *rpl_instance_predicate_match(rpl_instance_t *instance, uint8_t pred, uint8_t instance_id, const uint8_t *dodagid, uint8_t version_num); void rpl_instance_inconsistency(rpl_instance_t *instance); void rpl_instance_consistent_rx(rpl_instance_t *instance); @@ -83,9 +84,10 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, struct protocol_interfac void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair); bool rpl_instance_local_repair(const rpl_instance_t *instance); uint16_t rpl_instance_current_rank(const rpl_instance_t *instance); +uint16_t rpl_instance_candidate_rank(const rpl_neighbour_t *candidate); bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr); bool rpl_instance_address_is_candidate(rpl_instance_t *instance, const uint8_t *ipv6_addr, uint16_t candidate_amount); -uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents); +uint16_t rpl_instance_address_candidate_count(const rpl_instance_t *instance, bool selected_parents); void rpl_instance_neighbor_delete(rpl_instance_t *instance, const uint8_t *ipv6_addr); void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds); @@ -133,6 +135,7 @@ void rpl_dodag_version_raise_greediness(rpl_dodag_version_t *version, uint16_t p bool rpl_dodag_version_rank_indicates_possible_sub_dodag(const rpl_dodag_version_t *version, uint16_t rank); rpl_neighbour_t *rpl_lookup_neighbour_by_ll_address(const rpl_instance_t *instance, const uint8_t *addr, int8_t if_id); +rpl_neighbour_t *rpl_lookup_last_candidate_from_list(const rpl_instance_t *instance); rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *instance, const uint8_t *ll_addr, int8_t if_id, uint8_t g_mop_prf, uint8_t dtsn); void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour); bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_t *conf, const uint8_t *src, bool *become_leaf); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index aa811687e0bb..ee6859314702 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -263,3 +263,18 @@ void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms) { } + +bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) +{ + return false; +} + +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank) +{ + return true; +} + +bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, uint8_t ll_addr[16]) +{ + return true; +} diff --git a/test/nanostack/unittest/stub/rpl_upward_stub.c b/test/nanostack/unittest/stub/rpl_upward_stub.c index cd4cdaadf32a..a310c8ebb206 100644 --- a/test/nanostack/unittest/stub/rpl_upward_stub.c +++ b/test/nanostack/unittest/stub/rpl_upward_stub.c @@ -193,6 +193,11 @@ rpl_neighbour_t *rpl_lookup_neighbour_by_ll_address(const rpl_instance_t *instan return NULL; } +rpl_neighbour_t *rpl_lookup_last_candidate_from_list(const rpl_instance_t *instance) +{ + return NULL; +} + rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *version, const uint8_t *addr, int8_t if_id, uint8_t g_mop_prf, uint8_t dtsn) { return NULL; @@ -488,9 +493,14 @@ void rpl_dodag_update_unpublished_dio_prefix_finish(rpl_dodag_t *dodag) } -uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents) +uint16_t rpl_instance_address_candidate_count(const rpl_instance_t *instance, bool selected_parents) { return 0; } +uint16_t rpl_instance_candidate_rank(const rpl_neighbour_t *candidate) +{ + return 0xffff; +} + #endif /* HAVE_RPL */ From 1b99fe18dfbf28a976cf2ed2a03a9dff652f44af Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 28 Nov 2019 10:14:09 +0200 Subject: [PATCH 12/88] Added ETX to rpl_possible_better_candidate ETX may be 0 when it is new neighbour and then etx is optimistic 128. Change-Id: Ic5ed0d453d04a16ead9d040217cd132b5d35e366 --- source/6LoWPAN/ws/ws_bootstrap.c | 41 ++++++++++++------- source/RPL/rpl_control.c | 7 ++-- source/RPL/rpl_control.h | 2 +- source/RPL/rpl_mrhof.c | 14 +++++-- source/RPL/rpl_objective.h | 2 +- source/RPL/rpl_of0.c | 5 ++- source/RPL/rpl_upward.c | 4 +- source/RPL/rpl_upward.h | 2 +- .../unittest/stub/rpl_control_stub.c | 2 +- .../nanostack/unittest/stub/rpl_upward_stub.c | 5 +++ 10 files changed, 54 insertions(+), 30 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index d598ccb608b7..2b13e16a9537 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2147,10 +2147,17 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, } uint8_t replacing[16]; - uint8_t mac64[8]; + uint8_t mac64[10]; bool replace_ok = false; bool create_ok = false; llc_neighbour_req_t neigh_buffer; + + //Discover neigh ready here for possible ETX validate + memcpy(mac64, ll_parent_address + 8, 8); + mac64[0] ^= 2; + + ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false); + if (rpl_control_candidate_list_size(cur, instance) < cur->ws_info->rpl_parent_candidate_max) { //Not reach max value yet accept then all go to create neigh table goto neigh_create; @@ -2161,20 +2168,22 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, return false; } - // if not yet probed, return false - memcpy(mac64, replacing + 8, 8); - mac64[0] ^= 2; + // +2 Is for PAN ID space + memcpy(mac64 + 2, replacing + 8, 8); + mac64[2] ^= 2; - if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { - //Verify that we have proped min 1 time - etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, neigh_buffer.neighbor->index); - if (etx_entry && etx_entry->etx_samples == 0) { - return false; - } + if (ws_etx_read(cur, ADDR_802_15_4_LONG, mac64) == 0xffff) { + //Not proped yet because ETX is 0xffff + return false; + } + + uint16_t etx = 0; + if (neigh_buffer.neighbor) { + etx = etx_local_etx_read(cur->id, neigh_buffer.neighbor->index); } // Accept now only better one's when max candidates slected and max candidate list size is reached - if (!rpl_possible_better_candidate(cur, instance, replacing, candidate_rank)) { + if (!rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx)) { return false; } //TODO if replacing has poor ETX, put it in blacklist as "poor ETX" to prevent reselection @@ -2183,14 +2192,16 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, neigh_create: - memcpy(mac64, ll_parent_address + 8, 8); - mac64[0] ^= 2; - if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { + + if (neigh_buffer.neighbor) { + //Use Already discovered entry create_ok = true; goto neigh_create_ok; } - //Discover Multicast temporary entry + //Discover Multicast temporary entry for create neighbour table entry for new candidate + memcpy(mac64, ll_parent_address + 8, 8); + mac64[0] ^= 2; ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); if (!entry) { return false; diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 697ba7b6ca53..a0a95eae18f2 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -272,7 +272,7 @@ bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interfa return false; } -bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, rpl_instance_t *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank) +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, rpl_instance_t *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx) { if (!interface->rpl_domain) { return false; @@ -283,7 +283,7 @@ bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interfa return false; } - return rpl_instance_possible_better_candidate(rpl_instance, neighbour, candidate_rank); + return rpl_instance_possible_better_candidate(rpl_instance, neighbour, candidate_rank, etx); } @@ -1847,9 +1847,8 @@ void rpl_control_print(route_print_fn_t *print_fn) unsigned s = s_full % 60; unsigned h = m / 60; m %= 60; - print_fn("Time %02u:%02u:%02u.%u (%u.%u)", h, m, s, t, s_full, t); // %zu doesn't work on some Mbed toolchains - print_fn("RPL memory usage %" PRIu32, (uint32_t) rpl_alloc_total); + print_fn("Time %02u:%02u:%02u.%u (%u.%u) RPL memory usage %" PRIu32, h, m, s, t, s_full, t, (uint32_t) rpl_alloc_total); ns_list_foreach(rpl_domain_t, domain, &rpl_domains) { rpl_domain_print(domain, print_fn); } diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 63967209e099..0987fbaa5410 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -155,7 +155,7 @@ void rpl_control_unpublish_address(rpl_domain_t *domain, const uint8_t addr[16]) bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); bool rpl_control_is_dodag_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint16_t candidate_cmp_limiter); bool rpl_control_probe_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); -bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank); +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx); uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list); uint16_t rpl_control_candidate_list_size(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance); void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); diff --git a/source/RPL/rpl_mrhof.c b/source/RPL/rpl_mrhof.c index 9581f595a08b..be3fd9a8229b 100644 --- a/source/RPL/rpl_mrhof.c +++ b/source/RPL/rpl_mrhof.c @@ -45,7 +45,7 @@ static void rpl_mrhof_parent_selection(rpl_instance_t *instance); static uint16_t rpl_mrhof_path_cost_through_neighbour(const rpl_neighbour_t *neighbour); static bool rpl_mrhof_neighbour_acceptable(const rpl_instance_t *instance, const rpl_neighbour_t *neighbour); -static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank); +static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank, uint16_t etx); static rpl_objective_t rpl_mrhof = { .ocp = RPL_OCP_MRHOF, @@ -96,7 +96,7 @@ static bool rpl_mrhof_neighbour_acceptable(const rpl_instance_t *instance, const return rpl_mrhof_link_metric_to_neighbour(neighbour) <= rpl_policy_mrhof_max_link_metric(instance->domain); } -static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank) +static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank, uint16_t etx) { uint16_t existing_path = rpl_mrhof_path_cost_through_neighbour(existing); // Optimistically assume we could get a perfect link to this new person @@ -105,7 +105,15 @@ static bool rpl_mrhof_possible_better_candidate(const rpl_instance_t *instance, // Think: could actually use rpl_mrhof_etx here to get an existing ETX estimate // (except that gives infinite if no current link, would want a variant that checks // blacklist records for remembered poor ETX) - uint16_t potential_path_with_hysteresis = rpl_rank_add(rank, 128 + rpl_policy_mrhof_parent_switch_threshold(instance->domain)); + uint16_t threshold = rpl_policy_mrhof_parent_switch_threshold(instance->domain); + if (etx == 0) { + etx = 128; + } else if (etx >= (0xffff - threshold)) { + return false; + } + + etx += threshold; + uint16_t potential_path_with_hysteresis = rpl_rank_add(rank, etx); return potential_path_with_hysteresis <= existing_path; } diff --git a/source/RPL/rpl_objective.h b/source/RPL/rpl_objective.h index fa36b0ce4cd3..7e8293a396ab 100644 --- a/source/RPL/rpl_objective.h +++ b/source/RPL/rpl_objective.h @@ -33,7 +33,7 @@ typedef struct rpl_objective { bool (*neighbour_acceptable)(const struct rpl_instance *, const struct rpl_neighbour *); /* Could someone with specified rank be a significantly better candidate than the existing one? */ /* (In future, this API could be extended to pass a metric pointer as well as rank) */ - bool (*possible_better_candidate)(const struct rpl_instance *, const struct rpl_neighbour *existing, uint16_t rank); + bool (*possible_better_candidate)(const struct rpl_instance *, const struct rpl_neighbour *existing, uint16_t rank, uint16_t etx); ns_list_link_t link; } rpl_objective_t; diff --git a/source/RPL/rpl_of0.c b/source/RPL/rpl_of0.c index 66a237c76022..bfdee2a49626 100644 --- a/source/RPL/rpl_of0.c +++ b/source/RPL/rpl_of0.c @@ -42,7 +42,7 @@ static void rpl_of0_parent_selection(rpl_instance_t *instance); static uint16_t rpl_of0_rank_through_neighbour(const rpl_neighbour_t *neighbour); static bool rpl_of0_neighbour_acceptable(const rpl_instance_t *instance, const rpl_neighbour_t *neighbour); -static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank); +static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank, uint16_t etx); static rpl_objective_t rpl_of0 = { .ocp = RPL_OCP_OF0, @@ -117,8 +117,9 @@ static uint16_t rpl_of0_rank_through_neighbour(const rpl_neighbour_t *neighbour) return rpl_rank_add(neighbour->rank, rpl_of0_rank_increase(neighbour)); } -static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank) +static bool rpl_of0_possible_better_candidate(const rpl_instance_t *instance, const rpl_neighbour_t *existing, uint16_t rank, uint16_t etx) { + (void)etx; uint16_t existing_path = rpl_of0_rank_through_neighbour(existing); uint16_t potential_path_with_hysteresis = rpl_rank_add(rank, 2 * rpl_policy_of0_rank_factor(instance->domain) * existing->dodag_version->dodag->config.min_hop_rank_increase); return potential_path_with_hysteresis <= existing_path; diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index d905a6dc808e..27ef1516cb03 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -290,9 +290,9 @@ uint16_t rpl_instance_candidate_rank(const rpl_neighbour_t *candidate) return candidate->rank; } -bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank) +bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank, uint16_t etx) { - return instance->of->possible_better_candidate(instance, replacing, candidate_rank); + return instance->of->possible_better_candidate(instance, replacing, candidate_rank, etx); } /* If we're a member of a DODAG Version matching the predicate in this instance, diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index 4ebc51d1f7ff..ebf386f8d42b 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -70,7 +70,7 @@ bool rpl_instance_am_root(const rpl_instance_t *instance); uint8_t rpl_instance_mop(const rpl_instance_t *instance); rpl_dodag_version_t *rpl_instance_current_dodag_version(const rpl_instance_t *instance); rpl_neighbour_t *rpl_instance_preferred_parent(const rpl_instance_t *instance); -bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank); +bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank, uint16_t etx); rpl_dodag_version_t *rpl_instance_predicate_match(rpl_instance_t *instance, uint8_t pred, uint8_t instance_id, const uint8_t *dodagid, uint8_t version_num); void rpl_instance_inconsistency(rpl_instance_t *instance); void rpl_instance_consistent_rx(rpl_instance_t *instance); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index ee6859314702..e31cd2f10657 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -269,7 +269,7 @@ bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interfa return false; } -bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank) +bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx) { return true; } diff --git a/test/nanostack/unittest/stub/rpl_upward_stub.c b/test/nanostack/unittest/stub/rpl_upward_stub.c index a310c8ebb206..5966ada3f49e 100644 --- a/test/nanostack/unittest/stub/rpl_upward_stub.c +++ b/test/nanostack/unittest/stub/rpl_upward_stub.c @@ -503,4 +503,9 @@ uint16_t rpl_instance_candidate_rank(const rpl_neighbour_t *candidate) return 0xffff; } +bool rpl_instance_possible_better_candidate(const rpl_instance_t *instance, rpl_neighbour_t *replacing, uint16_t candidate_rank, uint16_t etx) +{ + return false; +} + #endif /* HAVE_RPL */ From 1f1c2a24fa95841590e65c466f54424d03420eb4 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 3 Dec 2019 13:36:13 +0200 Subject: [PATCH 13/88] Test purpose change. Change-Id: I708c208a9154d117e442b02db3539191042a2216 --- source/6LoWPAN/ws/ws_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 2504fb910f3e..9ff0007021bd 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -31,7 +31,7 @@ #define WS_RPL_DIO_DOUBLING 2 #define WS_RPL_DIO_REDUNDANCY 0 -#define WS_RPL_MIN_HOP_RANK_INCREASE 160 +#define WS_RPL_MIN_HOP_RANK_INCREASE 196 #define WS_RPL_MAX_HOP_RANK_INCREASE 2048 #define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128 From 6867dd7b2734a35a28fbf2e92b194aa532bf5a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Mon, 2 Dec 2019 11:34:07 +0200 Subject: [PATCH 14/88] Suplicant EAP-TLS timeout is not incremented from retries Supplicant no longer resets wait timer for EAP-TLS retries when receiving retried TLS packet from Authenticator (has same EAP-TLS sequence number). Moved GTK/GAK trace under EXTRA_DEBUG_INFO flag on controller. --- source/6LoWPAN/ws/ws_pae_controller.c | 12 +++++--- .../eap_tls_sec_prot/supp_eap_tls_sec_prot.c | 29 +++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 14f0aeca8d2d..4cb64cf9ea39 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -365,12 +365,16 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_ if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) { // Install the new network key derived from GTK and network name (GAK) to MAC controller->nw_key_set(interface_ptr, i, i, gak); - tr_info("NW: %s", controller->network_name); - tr_info("NW: %s", trace_array((uint8_t *)controller->network_name, 20)); - tr_info("GTK: %s", trace_array(gtk, 16)); - tr_info("GAK: %s", trace_array(gak, 16)); nw_key[i].installed = true; ret = 0; +#ifdef EXTRA_DEBUG_INFO + tr_info("NW name: %s", controller->network_name); + size_t nw_name_len = strlen(controller->network_name); + tr_info("NW name: %s", trace_array((uint8_t *)controller->network_name, nw_name_len)); + tr_info("GTK: %s", trace_array(gtk, 16)); + tr_info("GAK: %s", trace_array(gak, 16)); +#endif + } else { tr_error("GAK generation failed network name: %s", controller->network_name); continue; diff --git a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c index b80a43cc404f..bac7ecceb4ae 100644 --- a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c @@ -72,10 +72,10 @@ typedef struct { bool send_pending: 1; /**< TLS data is not yet send to network */ } eap_tls_sec_prot_int_t; -#define FWH_RETRY_TIMEOUT_SMALL 330*10 // retry timeout for small network additional 30 seconds for authenticator delay -#define FWH_RETRY_TIMEOUT_LARGE 750*10 // retry timeout for large network additional 30 seconds for authenticator delay +#define EAP_TLS_RETRY_TIMEOUT_SMALL 330*10 // retry timeout for small network additional 30 seconds for authenticator delay +#define EAP_TLS_RETRY_TIMEOUT_LARGE 750*10 // retry timeout for large network additional 30 seconds for authenticator delay -static uint16_t retry_timeout = FWH_RETRY_TIMEOUT_SMALL; +static uint16_t retry_timeout = EAP_TLS_RETRY_TIMEOUT_SMALL; static uint16_t supp_eap_tls_sec_prot_size(void); static int8_t supp_eap_tls_sec_prot_init(sec_prot_t *prot); @@ -93,7 +93,7 @@ static void supp_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks static int8_t supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot); static void supp_eap_tls_sec_prot_delete_tls(sec_prot_t *prot); -static void supp_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot); +static bool supp_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot); #define eap_tls_sec_prot_get(prot) (eap_tls_sec_prot_int_t *) &prot->data @@ -113,9 +113,9 @@ int8_t supp_eap_tls_sec_prot_register(kmp_service_t *service) int8_t supp_eap_sec_prot_timing_adjust(uint8_t timing) { if (timing < 16) { - retry_timeout = FWH_RETRY_TIMEOUT_SMALL; + retry_timeout = EAP_TLS_RETRY_TIMEOUT_SMALL; } else { - retry_timeout = FWH_RETRY_TIMEOUT_LARGE; + retry_timeout = EAP_TLS_RETRY_TIMEOUT_LARGE; } return 0; } @@ -493,7 +493,10 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) } // Store sequence ID - supp_eap_tls_sec_prot_seq_id_update(prot); + if (supp_eap_tls_sec_prot_seq_id_update(prot)) { + // When receiving a new sequence number, adds more time for re-send if no response + data->common.ticks = retry_timeout; + } // All fragments received for a message if (result == EAP_TLS_MSG_RECEIVE_DONE && data->tls_ongoing) { @@ -524,10 +527,6 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // Send EAP response supp_eap_tls_sec_prot_message_send(prot, EAP_RESPONSE, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING); data->send_pending = false; - - // Add more time for re-send if no response - data->common.ticks = retry_timeout; - break; case EAP_TLS_STATE_FINISH: @@ -550,10 +549,16 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) } } -static void supp_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot) +static bool supp_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot) { eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + bool new_seq_id = false; + + if (data->recv_eapol_pdu.msg.eap.id_seq > data->eap_id_seq) { + new_seq_id = true; + } data->eap_id_seq = data->recv_eapol_pdu.msg.eap.id_seq; + return new_seq_id; } #endif /* HAVE_WS */ From a58c71b96b8dd2944dabda71949904f42375420e Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 4 Dec 2019 15:04:16 +0200 Subject: [PATCH 15/88] Trace level updates (#2247) --- source/6LoWPAN/ws/ws_bootstrap.c | 6 +++--- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 4 ++-- source/NWK_INTERFACE/protocol_core.c | 4 ++-- source/RPL/rpl_upward.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 2b13e16a9537..fd63ba516bdd 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -201,7 +201,7 @@ static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur) { if (cur->bootStrapId < 0) { cur->bootStrapId = eventOS_event_handler_create(&ws_bootstrap_event_handler, WS_INIT_EVENT); - tr_debug("WS tasklet init"); + tr_info("WS tasklet init"); } if (cur->bootStrapId < 0) { @@ -807,7 +807,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) return -1; } - tr_debug("Wi-SUN ifdown"); + tr_info("Wi-SUN ifdown"); // Reset WS information // ws_common_reset(cur) @@ -2639,7 +2639,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pcs_running = false; if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - tr_debug("Border router start network"); + tr_info("Border router start network"); if (!ws_bbr_ready_to_start(cur)) { // Wi-SUN not started yet we wait for Border router permission diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 1ea990f2e054..c186d0a3811b 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1321,7 +1321,7 @@ static void mac_common_data_confirmation_handle(protocol_interface_rf_mac_setup_ timer_mac_stop(rf_mac_setup); if (m_event == MAC_CCA_FAIL) { sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_CCA_FAIL, 0); - tr_debug("MAC CCA fail"); + tr_info("MAC CCA fail"); /* CCA fail */ //rf_mac_setup->cca_failure++; buf->status = MLME_BUSY_CHAN; @@ -1329,7 +1329,7 @@ static void mac_common_data_confirmation_handle(protocol_interface_rf_mac_setup_ sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_COUNT, buf->mac_payload_length); if (m_event == MAC_TX_FAIL) { sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_FAIL, 0); - tr_debug("MAC tx fail"); + tr_info("MAC tx fail"); buf->status = MLME_TX_NO_ACK; } else if (m_event == MAC_TX_DONE) { if (mac_is_ack_request_set(buf) == false) { diff --git a/source/NWK_INTERFACE/protocol_core.c b/source/NWK_INTERFACE/protocol_core.c index 2d8c99f4c13b..f51599eb99e5 100644 --- a/source/NWK_INTERFACE/protocol_core.c +++ b/source/NWK_INTERFACE/protocol_core.c @@ -1116,10 +1116,10 @@ void nwk_bootsrap_state_update(arm_nwk_interface_status_type_e posted_event, pro default: mac_data_poll_protocol_poll_mode_disable(cur); if (!cur->rpl_domain) { - tr_debug("NON RPL Ready"); + tr_info("NON RPL Ready"); //nwk_protocol_poll_mode_disable(cur->nwk_id, 0); } else { - tr_debug("RPL Ready"); + tr_info("RPL Ready"); } } } else { diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 27ef1516cb03..4af67935671b 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1477,7 +1477,7 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) if (original_preferred != preferred_parent) { protocol_stats_update(STATS_RPL_PARENT_CHANGE, 1); if (preferred_parent) { - tr_debug("New preferred parent %s", trace_array(preferred_parent->ll_address, 16)); + tr_info("New preferred parent %s", trace_array(preferred_parent->ll_address, 16)); } } From c387fda2384239f3735afc2932b7b0f49709bbc4 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 4 Dec 2019 10:38:05 +0200 Subject: [PATCH 16/88] NS Probe limiter accept only 2 probe at 16 seconds period. Change-Id: If5e9cc443fa8a43ff4b8b00dadc0a2d97d887e1f --- source/6LoWPAN/ws/ws_bootstrap.c | 28 ++++++++++++++++++++++++++++ source/6LoWPAN/ws/ws_common.h | 3 +++ source/RPL/rpl_policy.c | 2 +- source/Service_Libs/etx/etx.c | 5 +++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index fd63ba516bdd..c9f55cb26e69 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1663,11 +1663,16 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, activate_nud = true; } else { + if (cur->ws_info->ns_probed_timer > 7) { + return false;//Accept 1 probe start / every seconds call + } + ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); if (!rpl_control_probe_parent_candidate(cur, ll_address)) { return false; } + uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples; uint32_t time_block = 1 << etx_entry->etx_samples; if (time_from_start >= probe_period) { @@ -1697,7 +1702,14 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, ws_neighbor->accelerated_etx_probe = false; entry->timer = 1; } + entry->nud_process = nud_proces; + if (!nud_proces) { + cur->ws_info->ns_probed_timer += 8; + if (cur->ws_info->ns_probed_timer > 32) { + cur->ws_info->ns_probed_timer = 32; + } + } return true; } @@ -2141,6 +2153,11 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, return false; } + if (cur->ws_info->ns_probed_timer > 8) { + //2 probe have been done so Try to avoid put more before accept new one's + return false; + } + if (blacklist_reject(ll_parent_address)) { // Rejected by blacklist return false; @@ -2158,6 +2175,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false); + if (rpl_control_candidate_list_size(cur, instance) < cur->ws_info->rpl_parent_candidate_max) { //Not reach max value yet accept then all go to create neigh table goto neigh_create; @@ -2637,6 +2655,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->ns_probed_timer = 0; if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); @@ -2953,6 +2972,15 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s ws_bootstrap_event_discovery_start(cur); } } + + //Probe limiter timer + if (cur->ws_info->ns_probed_timer) { + if (cur->ws_info->ns_probed_timer > seconds) { + cur->ws_info->ns_probed_timer -= seconds; + } else { + cur->ws_info->ns_probed_timer = 0; + } + } } void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index a901d08b27d7..5d2c3051e16a 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -91,6 +91,9 @@ typedef struct ws_info_s { // default fhss parameters for this device uint8_t fhss_uc_dwell_interval; uint8_t fhss_bc_dwell_interval; + //NS Probe lmiter + uint32_t ns_probed_timer; + uint32_t fhss_bc_interval; uint8_t fhss_uc_channel_function; uint8_t fhss_bc_channel_function; diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index ec581c8bb421..a9841212943a 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -238,7 +238,7 @@ uint16_t rpl_policy_dio_parent_selection_delay(rpl_domain_t *domain) { (void)domain; - return 15; /* seconds */ + return 19; /* seconds */ } uint16_t rpl_policy_repair_initial_dis_delay(rpl_domain_t *domain) diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 60dc5a91fcec..2f79457555ee 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -202,6 +202,7 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ if (!entry) { return; } + if (entry->etx_samples < 7) { entry->etx_samples++; } @@ -216,6 +217,10 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ } etx_calculation(entry, storage->attempts_count, storage->received_acks, attribute_index); + + if (entry->etx_samples < 7 && !success) { + entry->etx_samples = 7; //Stop Probing to failure + } return; } From 4ff02f97705e488528b6e9da03ff07643c07824d Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 4 Dec 2019 16:08:55 +0200 Subject: [PATCH 17/88] Stop sending normal ACK if neighbour is Unknown. Change-Id: If2259947559df2bf3df685ec5741f6c8ef467b11 --- source/6LoWPAN/ws/ws_llc_data_service.c | 2 +- source/MAC/IEEE802_15_4/mac_pd_sap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 00523518eb04..9e94dbbe4cb8 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -560,7 +560,7 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, request_new_entry)) { if (!multicast || ws_utt.message_type == WS_FT_EAPOL) { - tr_debug("Drop message no neighbor"); + //tr_debug("Drop message no neighbor"); return; } else { //Allocate temporary entry diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index a7a5cc2a89dc..a0371a47fb35 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -772,7 +772,7 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr, return -1; } - if (rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0 || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) { + if (mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) { rf_ptr->ack_tx_possible = true; } else { rf_ptr->ack_tx_possible = false; From 0aead9305a9c311031dab88a9fb7d496fe06557f Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 5 Dec 2019 10:22:00 +0200 Subject: [PATCH 18/88] Wi-sun Probe functionality revert operation Removed Probe purge. Removed Neighbour Replacementation from wi-sun side. Added same Candidate accept rules than earlier. Change-Id: Ia6140d6dddf1c5dd19af720a96b145448aace0fa --- source/6LoWPAN/ws/ws_bootstrap.c | 96 +++++++++++-------- source/6LoWPAN/ws/ws_common.h | 3 - source/RPL/rpl_control.c | 10 ++ source/RPL/rpl_control.h | 1 + source/RPL/rpl_policy.c | 2 +- source/RPL/rpl_upward.c | 1 + .../unittest/stub/rpl_control_stub.c | 5 + 7 files changed, 76 insertions(+), 42 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index c9f55cb26e69..a3d554f719ae 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1663,10 +1663,6 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, activate_nud = true; } else { - if (cur->ws_info->ns_probed_timer > 7) { - return false;//Accept 1 probe start / every seconds call - } - ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); if (!rpl_control_probe_parent_candidate(cur, ll_address)) { return false; @@ -1704,12 +1700,6 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, } entry->nud_process = nud_proces; - if (!nud_proces) { - cur->ws_info->ns_probed_timer += 8; - if (cur->ws_info->ns_probed_timer > 32) { - cur->ws_info->ns_probed_timer = 32; - } - } return true; } @@ -2145,16 +2135,26 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t } } -static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank) +static bool ws_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) { + //Already many candidates + if (rpl_control_candidate_list_size(cur, instance) > cur->ws_info->rpl_parent_candidate_max) { + return false; + } - protocol_interface_info_entry_t *cur = handle; - if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + //Already enough selected candidates + if (rpl_control_selected_parent_count(cur, instance) >= cur->ws_info->rpl_selected_parent_max) { return false; } - if (cur->ws_info->ns_probed_timer > 8) { - //2 probe have been done so Try to avoid put more before accept new one's + return true; +} + +static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank) +{ + + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { return false; } @@ -2163,25 +2163,54 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, return false; } - uint8_t replacing[16]; uint8_t mac64[10]; - bool replace_ok = false; - bool create_ok = false; + //bool replace_ok = false; + //bool create_ok = false; llc_neighbour_req_t neigh_buffer; //Discover neigh ready here for possible ETX validate memcpy(mac64, ll_parent_address + 8, 8); mac64[0] ^= 2; + ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false); + //Discover Multicast temporary entry for create neighbour table entry for new candidate + ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); + if (!ws_rpl_candidate_soft_filtering(cur, instance)) { + if (!neigh_buffer.neighbor) { + //Do not accept any new in that Place + return false; + } - if (rpl_control_candidate_list_size(cur, instance) < cur->ws_info->rpl_parent_candidate_max) { - //Not reach max value yet accept then all go to create neigh table - goto neigh_create; - } + uint8_t replacing[16]; + //Accept Know neighbour if it is enough good + if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) { + return false; + } + // +2 Is for PAN ID space + memcpy(mac64 + 2, replacing + 8, 8); + mac64[2] ^= 2; + + if (ws_etx_read(cur, ADDR_802_15_4_LONG, mac64) == 0xffff) { + //Not proped yet because ETX is 0xffff + return false; + } + uint16_t etx = 0; + if (neigh_buffer.neighbor) { + etx = etx_local_etx_read(cur->id, neigh_buffer.neighbor->index); + } + // Accept now only better one's when max candidates selected and max candidate list size is reached + return rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx); + } + + //Neighbour allready + if (neigh_buffer.neighbor) { + return true; + } +#if 0 if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) { return false; } @@ -2200,7 +2229,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, etx = etx_local_etx_read(cur->id, neigh_buffer.neighbor->index); } - // Accept now only better one's when max candidates slected and max candidate list size is reached + // Accept now only better one's when max candidates selected and max candidate list size is reached if (!rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx)) { return false; } @@ -2216,16 +2245,15 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, create_ok = true; goto neigh_create_ok; } +#endif - //Discover Multicast temporary entry for create neighbour table entry for new candidate - memcpy(mac64, ll_parent_address + 8, 8); - mac64[0] ^= 2; - ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); if (!entry) { + //No Multicast Entry Available return false; } + //Create entry - create_ok = ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, true); + bool create_ok = ws_bootstrap_neighbor_info_request(cur, entry->mac64, &neigh_buffer, true); if (create_ok) { ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; //Copy fhss temporary data @@ -2236,6 +2264,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, } ws_llc_free_multicast_temp_entry(cur, entry); +#if 0 neigh_create_ok: if (create_ok && replace_ok) { @@ -2243,6 +2272,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, tr_debug("Remove %s by %s", trace_ipv6(replacing), trace_ipv6(ll_parent_address)); rpl_control_neighbor_delete_from_instance(cur, instance, replacing); } +#endif return create_ok; } @@ -2655,7 +2685,6 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; - cur->ws_info->ns_probed_timer = 0; if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); @@ -2972,15 +3001,6 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s ws_bootstrap_event_discovery_start(cur); } } - - //Probe limiter timer - if (cur->ws_info->ns_probed_timer) { - if (cur->ws_info->ns_probed_timer > seconds) { - cur->ws_info->ns_probed_timer -= seconds; - } else { - cur->ws_info->ns_probed_timer = 0; - } - } } void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 5d2c3051e16a..a901d08b27d7 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -91,9 +91,6 @@ typedef struct ws_info_s { // default fhss parameters for this device uint8_t fhss_uc_dwell_interval; uint8_t fhss_bc_dwell_interval; - //NS Probe lmiter - uint32_t ns_probed_timer; - uint32_t fhss_bc_interval; uint8_t fhss_uc_channel_function; uint8_t fhss_bc_channel_function; diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index a0a95eae18f2..06c704f5f653 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -257,6 +257,16 @@ uint16_t rpl_control_candidate_list_size(protocol_interface_info_entry_t *interf } +uint16_t rpl_control_selected_parent_count(protocol_interface_info_entry_t *interface, rpl_instance_t *rpl_instance) +{ + if (!interface->rpl_domain) { + return 0; + } + + return rpl_instance_address_candidate_count(rpl_instance, true); + +} + bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) { diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 0987fbaa5410..013799e96514 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -158,6 +158,7 @@ bool rpl_control_probe_parent_candidate(struct protocol_interface_info_entry *in bool rpl_possible_better_candidate(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16], uint16_t candidate_rank, uint16_t etx); uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list); uint16_t rpl_control_candidate_list_size(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance); +uint16_t rpl_control_selected_parent_count(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance); void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]); void rpl_control_neighbor_delete_from_instance(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, const uint8_t ll_addr[16]); bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *interface, struct rpl_instance *rpl_instance, uint8_t ll_addr[16]); diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index a9841212943a..ec581c8bb421 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -238,7 +238,7 @@ uint16_t rpl_policy_dio_parent_selection_delay(rpl_domain_t *domain) { (void)domain; - return 19; /* seconds */ + return 15; /* seconds */ } uint16_t rpl_policy_repair_initial_dis_delay(rpl_domain_t *domain) diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 4af67935671b..a50b6dc64ae5 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -356,6 +356,7 @@ void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t de { if (instance->parent_selection_timer == 0 || instance->parent_selection_timer > delay) { instance->parent_selection_timer = randLIB_randomise_base(delay, 0x7333, 0x8CCD) /* +/- 10% */; + tr_debug("Timed parent triggered %u", instance->parent_selection_timer); } } diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index e31cd2f10657..70271fe12335 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -278,3 +278,8 @@ bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *inter { return true; } + +uint16_t rpl_control_selected_parent_count(protocol_interface_info_entry_t *interface, rpl_instance_t *rpl_instance) +{ + return 0; +} From 6919ba130192c51b52d7b3b84320bc6cfedb73e1 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Mon, 2 Dec 2019 09:28:22 +0200 Subject: [PATCH 19/88] Wi-sun New key index activate. Delayed default key index activate after first config message confirmation. Change-Id: Ibcfbe82ad651f6ad4570180cade192406d566d8d --- source/6LoWPAN/ws/ws_bootstrap.c | 33 ++++++++++++++++++++++++---- source/6LoWPAN/ws/ws_common.c | 3 +++ source/6LoWPAN/ws/ws_common.h | 10 +++++++++ source/NWK_INTERFACE/protocol_core.c | 1 + 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index a3d554f719ae..535b018aba5c 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1465,8 +1465,13 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c static void ws_bootstrap_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) { ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1); - (void)interface; - (void)asynch_message; + if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + if (asynch_message == WS_FT_PAN_CONF && interface->ws_info->pending_key_index_info.state == PENDING_KEY_INDEX_ACTIVATE) { + interface->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; + tr_info("Activate new default key %u", interface->ws_info->pending_key_index_info.index + 1); + mac_helper_security_auto_request_key_index_set(interface, interface->ws_info->pending_key_index_info.index, interface->ws_info->pending_key_index_info.index + 1); + } + } } uint32_t ws_time_from_last_unicast_traffic(uint32_t current_time_stamp, ws_neighbor_class_entry_t *ws_neighbor) @@ -2410,7 +2415,16 @@ static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index) { - // Set send key + + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + if (cur->mac_parameters->mac_default_key_index != 0 && cur->mac_parameters->mac_default_key_index != index + 1) { + tr_info("New Pending key Request %u", index + 1); + cur->ws_info->pending_key_index_info.state = PENDING_KEY_INDEX_ADVERTISMENT; + cur->ws_info->pending_key_index_info.index = index; + return; + } + } + mac_helper_security_auto_request_key_index_set(cur, index, index + 1); } @@ -2660,7 +2674,13 @@ static void ws_bootstrap_pan_config(protocol_interface_info_entry_t *cur) async_req.security.SecurityLevel = mac_helper_default_security_level_get(cur); async_req.security.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur); - async_req.security.KeyIndex = mac_helper_default_key_index_get(cur); + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && cur->ws_info->pending_key_index_info.state == PENDING_KEY_INDEX_ADVERTISMENT) { + async_req.security.KeyIndex = cur->ws_info->pending_key_index_info.index + 1; + cur->ws_info->pending_key_index_info.state = PENDING_KEY_INDEX_ACTIVATE; + } else { + async_req.security.KeyIndex = mac_helper_default_key_index_get(cur); + } + ws_llc_asynch_request(cur, &async_req); } @@ -2680,6 +2700,11 @@ static void ws_bootstrap_event_handler(arm_event_s *event) break; case WS_DISCOVERY_START: tr_info("Discovery start"); + + //Clear Pending Key Index State + cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; + cur->mac_parameters->mac_default_key_index = 0; + // All trickle timers stopped to allow entry from any state cur->ws_info->trickle_pa_running = false; cur->ws_info->trickle_pc_running = false; diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 449a4d8e0d87..92792c393ab6 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -316,6 +316,9 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur) cur->ws_info->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL; cur->ws_info->fhss_uc_channel_function = WS_DH1CF; cur->ws_info->fhss_bc_channel_function = WS_DH1CF; + + cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; + for (uint8_t n = 0; n < 8; n++) { cur->ws_info->fhss_channel_mask[n] = 0xffffffff; } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index a901d08b27d7..18cb9fe14407 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -60,6 +60,15 @@ typedef struct ws_nud_table_entry { ns_list_link_t link; } ws_nud_table_entry_t; +#define NO_PENDING_PROCESS 0 +#define PENDING_KEY_INDEX_ADVERTISMENT 1 +#define PENDING_KEY_INDEX_ACTIVATE 2 + +typedef struct { + unsigned state: 2; + uint8_t index; +} ws_pending_key_index_t; + typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; typedef struct ws_info_s { @@ -88,6 +97,7 @@ typedef struct ws_info_s { bool trickle_pcs_running: 1; bool trickle_pc_running: 1; bool fhss_owner: 1; + ws_pending_key_index_t pending_key_index_info; // default fhss parameters for this device uint8_t fhss_uc_dwell_interval; uint8_t fhss_bc_dwell_interval; diff --git a/source/NWK_INTERFACE/protocol_core.c b/source/NWK_INTERFACE/protocol_core.c index f51599eb99e5..279bc7f0df61 100644 --- a/source/NWK_INTERFACE/protocol_core.c +++ b/source/NWK_INTERFACE/protocol_core.c @@ -603,6 +603,7 @@ static protocol_interface_info_entry_t *protocol_core_interface_6lowpan_entry_ge entry->mac_parameters->mac_prev_key_attribute_id = 0; entry->mac_parameters->mac_default_key_attribute_id = 1; entry->mac_parameters->mac_next_key_attribute_id = 2; + entry->mac_parameters->mac_default_key_index = 0; entry->beacon_cb = beacon_received; From 81740b8b1da230313dc98a0e4255c46479fb9933 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Mon, 9 Dec 2019 15:15:15 +0200 Subject: [PATCH 20/88] Wi-sun bootstarp update nad balck list trace level update Wi-sun EAPOL parent select may fail if device neighbour entry create fail and now we remove current parent and select next one. Change-Id: I317ff92686b2cf1ce00338bb14ad57cd7f01d96c --- source/6LoWPAN/ws/ws_bootstrap.c | 9 ++++++++- source/Service_Libs/blacklist/blacklist.c | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 535b018aba5c..26cdae94f8bb 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2833,6 +2833,7 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) tr_debug("analyze network discovery result"); +select_best_candidate: selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur); if (!selected_parent_ptr) { @@ -2851,7 +2852,13 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) ws_bootstrap_fhss_activate(cur); llc_neighbour_req_t neighbor_info; if (!ws_bootstrap_neighbor_info_request(cur, selected_parent_ptr->addr, &neighbor_info, true)) { - return; + //Remove Neighbour and set Link setup back + ns_list_remove(&cur->ws_info->parent_list_reserved, selected_parent_ptr); + ns_list_add_to_end(&cur->ws_info->parent_list_free, selected_parent_ptr); + // Configure LLC for network discovery + ws_bootstrap_network_discovery_configure(cur); + ws_bootstrap_fhss_activate(cur); + goto select_best_candidate; } ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_utt, selected_parent_ptr->timestamp); diff --git a/source/Service_Libs/blacklist/blacklist.c b/source/Service_Libs/blacklist/blacklist.c index 25d06666389e..f47b2097bff3 100644 --- a/source/Service_Libs/blacklist/blacklist.c +++ b/source/Service_Libs/blacklist/blacklist.c @@ -87,7 +87,7 @@ bool blacklist_reject(const uint8_t *ll64_address) if (blacklist_entry) { // If address is blacklisted rejects if (blacklist_entry->ttl > blacklist_data->blacklist_entry_lifetime) { - tr_debug("blacklist reject: %s", trace_array(ll64_address + 8, 8)); + tr_info("blacklist reject: %s", trace_array(ll64_address + 8, 8)); return true; // Neighbor heard; updates blacklist entry TTL to full lifetime } else { @@ -131,7 +131,7 @@ void blacklist_update(const uint8_t *ll64_address, bool success) // On successful link establishment remove address from blacklist if (success) { if (blacklist_entry) { - tr_debug("Blacklist removed"); + tr_info("Blacklist removed"); blacklist_entry_free(blacklist_entry); } // On failure add address to blacklist or update timeout @@ -144,7 +144,7 @@ void blacklist_update(const uint8_t *ll64_address, bool success) /* TTL is blacklist entry lifetime + from 1.0 to 1.5 * interval */ blacklist_entry->ttl = blacklist_data->blacklist_entry_lifetime + randLIB_randomise_base(blacklist_entry->interval, 0x8000, 0xC000); } else { - tr_debug("Blacklist add"); + tr_info("Blacklist add"); blacklist_entry_add(ll64_address + 8); } } @@ -209,7 +209,7 @@ void blacklist_ttl_update(uint16_t ticks) if (blacklist_entry->ttl > ticks) { blacklist_entry->ttl -= ticks; } else { - tr_debug("Blacklist remove entry: %s", trace_array(blacklist_entry->eui64, 8)); + tr_info("Blacklist remove entry: %s", trace_array(blacklist_entry->eui64, 8)); blacklist_entry_free(blacklist_entry); } } From 38df5768c507b94aa7a03ad4c7543f25f6d9c9cc Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 10 Dec 2019 10:00:02 +0200 Subject: [PATCH 21/88] Wi-sun advertisment consistent update Border router never set consistent rule Node set consistent when it here same pan size. Change-Id: Iea3aad92b6c146bce92f29478686b614119909f6 --- source/6LoWPAN/ws/ws_bootstrap.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 26cdae94f8bb..63f17f4736ae 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -898,11 +898,15 @@ static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interf * that of the receiving node, and PAN-IE / Routing Cost better than (smaller than) that of the receiving node. * */ - + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //Border router never set consistent that will guarantee that BR will send advertisment + return; + } #ifdef WISUN_1_0_ERRATA_FIX - (void)pan_information; - // All messages are considered as consistent only Solicit will cause inconsistent - trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + if (pan_information->pan_size == cur->ws_info->pan_information.pan_size) { + //If same pan size information then set consistent value + trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + } #else // Wi-SUN 1.0 specified functionality, causes extra inconsistencies when we hear higher rank advertisements if (pan_information->routing_cost >= ws_bootstrap_routing_cost_calculate(cur)) { From 1090430622ce4e01275cdf4a9941eb500853c4d4 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 11 Dec 2019 09:42:42 +0200 Subject: [PATCH 22/88] Trickle API update and Wi-SUN config sol state timeout update Trickle have a new API for ask max time for given expiration count. Wi-sun config sol timeout now also timer based. Earlier it was timeouting only after max config sol TX period. New solution works now better with larger network where config sol send is suppressed. Change-Id: I0f0bca34ea5a767685a6127f1b1e3a9c2dbc2d8e --- source/6LoWPAN/ws/ws_bootstrap.c | 32 +++++++++++++++------ source/6LoWPAN/ws/ws_common.h | 1 + source/Service_Libs/Trickle/trickle.c | 20 +++++++++++++ source/Service_Libs/Trickle/trickle.h | 5 ++++ test/nanostack/unittest/stub/trickle_stub.c | 5 ++++ 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 63f17f4736ae..2d122641814a 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2481,6 +2481,8 @@ static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry ws_bootstrap_ip_stack_reset(cur); cur->ws_info->pas_requests = 0; + //Calculate max time for config learn state + cur->ws_info->pan_config_sol_max_timeout = trickle_timer_max(&cur->ws_info->trickle_params_pan_discovery, PCS_MAX); // Reset advertisement solicit trickle to start discovering network cur->ws_info->trickle_pcs_running = true; trickle_start(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); @@ -2995,20 +2997,34 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t tr_info("Send PAN advertisement Solicit"); ws_bootstrap_pan_advert_solicit(cur); } - if (cur->ws_info->trickle_pcs_running && - trickle_timer(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery, ticks)) { - // send PAN Configuration solicit - if (cur->ws_info->pas_requests >= PCS_MAX) { - // if MAX PCS sent restart discovery + if (cur->ws_info->trickle_pcs_running) { + //Update MAX config sol timeout timer + if (cur->ws_info->pan_config_sol_max_timeout > ticks) { + cur->ws_info->pan_config_sol_max_timeout -= ticks; + } else { + //Config sol state timeout + cur->ws_info->pan_config_sol_max_timeout = 0; + } + + if (trickle_timer(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery, ticks)) { + if (cur->ws_info->pas_requests < PCS_MAX) { + // send PAN Configuration solicit + tr_info("Send PAN configuration Solicit"); + ws_bootstrap_pan_config_solicit(cur); + } + //Update counter every time reason that we detect PCS_MAX higher state + cur->ws_info->pas_requests++; + } + + if (cur->ws_info->pas_requests > PCS_MAX || cur->ws_info->pan_config_sol_max_timeout == 0) { + // if MAX PCS sent or max waited timeout restart discovery // Trickle is reseted when entering to discovery from state 3 + tr_info("PAN configuration Solicit timeout"); trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); ws_bootstrap_event_discovery_start(cur); return; } - tr_info("Send PAN configuration Solicit"); - cur->ws_info->pas_requests++; - ws_bootstrap_pan_config_solicit(cur); } if (cur->ws_info->trickle_pa_running && trickle_timer(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery, ticks)) { diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 18cb9fe14407..4fae3664f93d 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -90,6 +90,7 @@ typedef struct ws_info_s { parent_info_list_t parent_list_reserved; uint32_t pan_version_timer; /**< border router version udate timeout */ uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ + uint32_t pan_config_sol_max_timeout; uint8_t gtkhash[32]; bool configuration_learned: 1; bool trickle_pas_running: 1; diff --git a/source/Service_Libs/Trickle/trickle.c b/source/Service_Libs/Trickle/trickle.c index 5eaa8a1fa69d..77e58d09ad67 100644 --- a/source/Service_Libs/Trickle/trickle.c +++ b/source/Service_Libs/Trickle/trickle.c @@ -49,6 +49,26 @@ void trickle_start(trickle_t *t, const trickle_params_t *params) trickle_begin_interval(t); } +uint32_t trickle_timer_max(const trickle_params_t *params, uint8_t trickle_timer_expiration) +{ + trickle_time_t time_I = params->Imin - 1; + uint32_t total_time = time_I; + while (trickle_timer_expiration) { + if (time_I <= TRICKLE_TIME_MAX / 2) { + time_I *= 2; + } else { + time_I = TRICKLE_TIME_MAX; + } + + if (time_I > params->Imax) { + time_I = params->Imax; + } + total_time += time_I; + trickle_timer_expiration--; + } + return total_time; +} + /* We don't expose the raw reset as API; users should use "inconsistent_heard". * This avoids repeated resets stopping transmission by restarting the interval. */ diff --git a/source/Service_Libs/Trickle/trickle.h b/source/Service_Libs/Trickle/trickle.h index 60ffa25f81ee..a6c957826c96 100644 --- a/source/Service_Libs/Trickle/trickle.h +++ b/source/Service_Libs/Trickle/trickle.h @@ -76,5 +76,10 @@ bool trickle_running(const trickle_t *t, const trickle_params_t *params); /* Stop the timer (by setting e to infinite) */ void trickle_stop(trickle_t *t); +/* + * Call return max time after n count expiration period 0 return 1 Imin - 1 period + * + */ +uint32_t trickle_timer_max(const trickle_params_t *params, uint8_t trickle_timer_expiration); #endif /* TRICKLE_H_ */ diff --git a/test/nanostack/unittest/stub/trickle_stub.c b/test/nanostack/unittest/stub/trickle_stub.c index 6bdbd3140c1b..b186d62da6bd 100644 --- a/test/nanostack/unittest/stub/trickle_stub.c +++ b/test/nanostack/unittest/stub/trickle_stub.c @@ -47,3 +47,8 @@ bool trickle_timer(trickle_t *t, const trickle_params_t *params, uint16_t ticks) { return false; } + +uint32_t trickle_timer_max(const trickle_params_t *params, uint8_t trickle_timer_expiration) +{ + return params->Imin; +} From 49686ccb3c44b130f1b8617a70fd7d347b8d52e1 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 12 Dec 2019 11:02:25 +0200 Subject: [PATCH 23/88] Wi-sun certification test setup update Updated selected parent to 4 which force to generate all 8 possible neighbour candidate use. Change-Id: I4e634a8c9117a535236b378d9ccf5bad53b849c8 --- source/6LoWPAN/ws/ws_common_defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index f9f07fe7011e..79398a1a339d 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -211,7 +211,7 @@ typedef struct ws_bs_ie { #define WS_RPL_SELECTED_PARENT_MAX 2 #define WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX 8 -#define WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX 3 +#define WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX 4 /** * Wi-sun spesific non-preferred prefix policy label From ec2ea92b71b4c9bb141953c782da8ffc9a5f7fbd Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Mon, 16 Dec 2019 11:43:49 +0200 Subject: [PATCH 24/88] Added RX and TX active times in PHY statistics (#2255) --- nanostack/platform/arm_hal_phy.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nanostack/platform/arm_hal_phy.h b/nanostack/platform/arm_hal_phy.h index 9f4e09937dbd..56e9591fe268 100644 --- a/nanostack/platform/arm_hal_phy.h +++ b/nanostack/platform/arm_hal_phy.h @@ -192,6 +192,8 @@ typedef struct phy_rf_statistics_s { uint32_t crc_fails; ///< CRC failures uint32_t tx_timeouts; ///< transmission timeouts uint32_t rx_timeouts; ///< reception timeouts + uint64_t tx_active_time; ///< transmission active time + uint64_t rx_active_time; ///< reception active time } phy_rf_statistics_s; /** Virtual data request */ From 33c48eb6472720b01359968abef091c29543bb40 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Mon, 16 Dec 2019 10:23:09 +0200 Subject: [PATCH 25/88] Removed NUD messages from registered children When we would send a NUD to check link status we skip it if there is a valid ARO registration for that neighbour --- source/6LoWPAN/ws/ws_bootstrap.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 2d122641814a..79bd40fece32 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1629,6 +1629,8 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { uint32_t time_from_start = entry_ptr->link_lifetime - entry_ptr->lifetime; + uint8_t ll_address[16]; + bool nud_proces = false; bool activate_nud = false; protocol_interface_info_entry_t *cur = user_data; @@ -1639,17 +1641,22 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, return false; } - uint8_t ll_address[16]; - bool nud_proces = false; + ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); + if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT) { - ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); + if (ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64)) { + // This is our child with valid ARO registration Change link timeout to future we check at 2 minute intervals + entry_ptr->lifetime = entry_ptr->lifetime + 120; + if (entry_ptr->lifetime > entry_ptr->link_lifetime) { + entry_ptr->lifetime = entry_ptr->link_lifetime; + } + return false; + } if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) { - if (!ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64)) { - //NUD Not needed for if neighbour is not child or parent candidate - return false; - } + //NUD Not needed for if neighbour is not parent candidate + return false; } if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT * 1.5) { From 1d82fd5a5dd149487fc3e444db5abbc7a998366c Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 18 Dec 2019 10:12:38 +0200 Subject: [PATCH 26/88] Wi-sun BBR route update fix Before add default route and Prefix based on route check that BBR backbone interface is configured. Change-Id: I79f2394e4ffd66d30e16f62e00b2341259ec4467 --- source/6LoWPAN/ws/ws_bbr_api.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index b658c0c434f2..ae778d6711f0 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -437,8 +437,9 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) if (configuration & BBR_GUA_ROUTE) { rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, true); } - ipv6_route_add_with_info(current_global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0); - + if (backbone_interface_id >= 0) { + ipv6_route_add_with_info(current_global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0); + } ws_bbr_dhcp_server_stop(cur, current_global_prefix); } // TODO add global prefix @@ -447,9 +448,11 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) tr_info("RPL global prefix activate %s", trace_ipv6_prefix(global_prefix, 64)); // Add default route to RPL // Enable default routing to backbone - if (ipv6_route_add_with_info(global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0) == NULL) { - tr_err("global route add failed"); - return; + if (backbone_interface_id >= 0) { + if (ipv6_route_add_with_info(global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0) == NULL) { + tr_err("global route add failed"); + return; + } } ws_bbr_dhcp_server_start(cur, global_prefix); rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false); From 1f77ad6964fe82e9aacc2b128bd9f860d82d9a89 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 18 Dec 2019 14:12:30 +0200 Subject: [PATCH 27/88] Updated trace levels (#2258) --- source/Common_Protocols/icmpv6.c | 2 +- source/RPL/rpl_control.c | 2 +- source/libDHCPv6/dhcp_service_api.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 5222fde7689c..1a0f2c3355d5 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -1713,7 +1713,7 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited, buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP); buf->interface = cur; - tr_debug("Build NA"); + tr_info("Build NA"); return (buf); } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 06c704f5f653..fb287496adc4 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -1263,7 +1263,7 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr const rpl_dio_route_list_t *routes = rpl_dodag_get_route_list(dodag); const prefix_list_t *prefixes = rpl_dodag_get_prefix_list(dodag); - tr_debug("transmit dio, rank: %x", rank); + tr_info("transmit dio, rank: %x", rank); protocol_interface_info_entry_t *downstream_if = protocol_stack_interface_info_get_by_id(domain->non_storing_downstream_interface); length = 24; if (conf) { diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index 8e321a9468f6..47c09ec5e260 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -842,7 +842,7 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) if (retval != 0) { tr_warn("dhcp service socket_sendto fails: %i", retval); } else { - tr_debug("dhcp service socket_sendto %s", trace_ipv6(msg_tr_ptr->addr.address)); + tr_info("dhcp service socket_sendto %s", trace_ipv6(msg_tr_ptr->addr.address)); } } bool dhcp_service_timer_tick(uint16_t ticks) From c9e3d8ef7428026ef9cedd86183b774b216a420d Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 18 Dec 2019 11:37:37 +0200 Subject: [PATCH 28/88] Interface down update 6lowpan, Thread and wi-sun interface down now call MLME_RESET(true) which disable, reset and free MAC memory before MAC user start clean own data. Change-Id: I4032aca35ce2d21646219853f459118976314b30 --- .../Generic/protocol_6lowpan_bootstrap.c | 2 ++ .../Generic/protocol_6lowpan_interface.c | 23 +++++++++++-------- .../Bootstraps/protocol_6lowpan_interface.h | 2 ++ source/6LoWPAN/Thread/thread_common.c | 2 ++ source/6LoWPAN/ws/ws_bootstrap.c | 3 ++- .../stub/protocol_6lowpan_interface_stub.c | 5 ++++ 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index e78b91c088a2..005e8d84e9e0 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1379,6 +1379,8 @@ static int8_t arm_6lowpan_bootstrap_down(protocol_interface_info_entry_t *cur) } cur->if_lowpan_security_params->mle_security_frame_counter = mle_service_security_get_frame_counter(cur->id); mle_service_interface_receiver_handler_update(cur->id, mle_6lowpan_message_handler); + // Reset MAC for safe upper layer memory free + protocol_mac_reset(cur); return nwk_6lowpan_down(cur); } #ifdef HAVE_6LOWPAN_ND diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_interface.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_interface.c index d3b0d16520be..92ea3ce7382d 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_interface.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_interface.c @@ -72,6 +72,15 @@ #include "6LoWPAN/Fragmentation/cipv6_fragmenter.h" #include "libNET/src/net_load_balance_internal.h" +void protocol_mac_reset(protocol_interface_info_entry_t *cur) +{ + if (cur->mac_api) { + mlme_reset_t reset; + reset.SetDefaultPIB = true; + cur->mac_api->mlme_req(cur->mac_api, MLME_RESET, &reset); + } +} + static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur) @@ -96,15 +105,11 @@ static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur) } if (cur->interface_mode == INTERFACE_UP) { - if (cur->mac_api) { - mlme_reset_t reset; - reset.SetDefaultPIB = true; - cur->mac_parameters->pan_id = 0xffff; - cur->mac_parameters->SecurityEnabled = false; - cur->mac_parameters->security_frame_counter = 0; - cur->mac_parameters->mac_security_level = 0; - cur->mac_api->mlme_req(cur->mac_api, MLME_RESET, &reset); - } + cur->mac_parameters->pan_id = 0xffff; + cur->mac_parameters->SecurityEnabled = false; + cur->mac_parameters->security_frame_counter = 0; + cur->mac_parameters->mac_security_level = 0; + protocol_mac_reset(cur); cur->interface_mode = INTERFACE_IDLE; net_load_balance_internal_state_activate(cur, false); } diff --git a/source/6LoWPAN/Bootstraps/protocol_6lowpan_interface.h b/source/6LoWPAN/Bootstraps/protocol_6lowpan_interface.h index bd7875c51469..017805735ca3 100644 --- a/source/6LoWPAN/Bootstraps/protocol_6lowpan_interface.h +++ b/source/6LoWPAN/Bootstraps/protocol_6lowpan_interface.h @@ -31,5 +31,7 @@ extern int8_t nwk_6lowpan_up(struct protocol_interface_info_entry *cur); */ extern int8_t nwk_6lowpan_down(struct protocol_interface_info_entry *cur); +extern void protocol_mac_reset(struct protocol_interface_info_entry *cur); + #endif /* PROTOCOL_6LOWPAN_INTERFACE_H_ */ diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 7bbfb739617c..bfea2ba7a9e1 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -240,6 +240,8 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur) tr_debug("SET thread Idle"); //stop polling mac_data_poll_disable(cur); + // Reset MAC for safe upper layer memory free + protocol_mac_reset(cur); //Clean mle table thread_neighbor_list_clean(cur); // store frame counters diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 79bd40fece32..71dca085899d 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -808,7 +808,8 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) } tr_info("Wi-SUN ifdown"); - + // Reset MAC for safe upper layer memory free + protocol_mac_reset(cur); // Reset WS information // ws_common_reset(cur) ws_llc_reset(cur); diff --git a/test/nanostack/unittest/stub/protocol_6lowpan_interface_stub.c b/test/nanostack/unittest/stub/protocol_6lowpan_interface_stub.c index 2dfa2be96a23..2ba3dd2208d3 100644 --- a/test/nanostack/unittest/stub/protocol_6lowpan_interface_stub.c +++ b/test/nanostack/unittest/stub/protocol_6lowpan_interface_stub.c @@ -75,3 +75,8 @@ int8_t nwk_6lowpan_down(protocol_interface_info_entry_t *cur) { return 0; } + +void protocol_mac_reset(struct protocol_interface_info_entry *cur) +{ + +} From 4481e8635a611ca07daffde4ce36268d5e6f1fac Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 18 Dec 2019 14:03:30 +0200 Subject: [PATCH 29/88] Updated trace level to info. Change-Id: I8e38a9c4f69dab724770d6f2aec2b33a78734b50 --- source/RPL/rpl_downward.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 607cca6168a7..9cc7d7912307 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -1786,7 +1786,7 @@ static bool rpl_instance_push_address_registration(protocol_interface_info_entry if (!buf) { return false; } - tr_debug("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address)); + tr_info("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address)); protocol_push(buf); return true; } From 04946065e469d8b33757e55072d32133e533be11 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 19 Dec 2019 11:03:32 +0200 Subject: [PATCH 30/88] Adapatation layer unicast list entry free update Added new parameter for reject fragmented buffer unnesessary free. Change-Id: Ifa5bd09ea7759aa4fb942d59d7d5d273e85ff4e9 --- source/6LoWPAN/adaptation_interface.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 73ca406e541a..c4fd8fe536fd 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -328,10 +328,14 @@ static void lowpan_list_entry_free(fragmenter_tx_list_t *list, fragmenter_tx_ent ns_dyn_mem_free(entry); } -static void lowpan_list_free(fragmenter_tx_list_t *list) +static void lowpan_list_free(fragmenter_tx_list_t *list, bool fragment_buf_free) { while (!ns_list_is_empty(list)) { fragmenter_tx_entry_t *entry = ns_list_get_first(list); + if (!fragment_buf_free) { + //We can't free this pointer becuase it must be until interface is deleted + entry->fragmenter_buf = NULL; + } lowpan_list_entry_free(list, entry); } } @@ -388,11 +392,11 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id) ns_list_remove(&fragmenter_interface_list, interface_ptr); //free active tx process - lowpan_list_free(&interface_ptr->activeUnicastList); + lowpan_list_free(&interface_ptr->activeUnicastList, false); lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Free Indirect entry - lowpan_list_free(&interface_ptr->indirect_tx_queue); + lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); @@ -413,13 +417,13 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) } //free active tx process - lowpan_list_free(&interface_ptr->activeUnicastList); + lowpan_list_free(&interface_ptr->activeUnicastList, false); lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Clean fragmented message flag interface_ptr->fragmenter_active = false; //Free Indirect entry - lowpan_list_free(&interface_ptr->indirect_tx_queue); + lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); From 11a1e1d2de52da795333af4e48e0f7c779cbc144 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 19 Dec 2019 15:13:28 +0200 Subject: [PATCH 31/88] Store TX start channel and black list if TX failed (#2261) --- nanostack/fhss_api.h | 3 ++- source/MAC/IEEE802_15_4/mac_defines.h | 1 + source/MAC/IEEE802_15_4/mac_mcps_sap.c | 3 ++- source/Service_Libs/fhss/fhss.c | 3 ++- source/Service_Libs/fhss/fhss_ws.c | 4 ++-- .../unittest/service_libs/fhss/test_fhss.c | 15 ++++++++------- .../unittest/service_libs/fhss_ws/test_fhss_ws.c | 13 +++++++------ test/nanostack/unittest/stub/fhss_config_stub.c | 2 +- test/nanostack/unittest/stub/fhss_config_stub.h | 2 +- 9 files changed, 26 insertions(+), 20 deletions(-) diff --git a/nanostack/fhss_api.h b/nanostack/fhss_api.h index 84c0c17c3264..be5a90c1d210 100644 --- a/nanostack/fhss_api.h +++ b/nanostack/fhss_api.h @@ -122,9 +122,10 @@ typedef void fhss_data_tx_done(const fhss_api_t *api, bool waiting_ack, bool tx_ * @param api FHSS instance. * @param handle Handle of the data request. * @param frame_type Frame type of packet (Frames types are defined by FHSS api). + * @param channel Channel wanted to black list temporarily. * @return true if frame has to be queued for retransmission, false otherwise. */ -typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_type); +typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_type, uint8_t channel); /** * @brief Change synchronization state. diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 7d534595458e..e7d1babeaa0d 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -202,6 +202,7 @@ typedef struct protocol_interface_rf_mac_setup { mac_scan_type_t scan_type; uint8_t mac_channel; + uint8_t mac_tx_start_channel; //uint8_t cca_failure; /* MAC TX Queue */ diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index c186d0a3811b..6442290a48ee 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1430,7 +1430,7 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, if (rf_ptr->fhss_api && !buffer->asynch_request) { // FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) { - if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) { + if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), rf_ptr->mac_tx_start_channel) == true) { if (rf_ptr->mac_tx_result == MAC_TX_FAIL) { buffer->fhss_retry_count += 1 + rf_ptr->mac_tx_status.retry; @@ -1921,6 +1921,7 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t)); rf_ptr->mac_cca_retry = 0; rf_ptr->mac_tx_retry = 0; + rf_ptr->mac_tx_start_channel = rf_ptr->mac_channel; mac_csma_param_init(rf_ptr); if (mcps_generic_packet_build(rf_ptr, buffer) != 0) { return -1; diff --git a/source/Service_Libs/fhss/fhss.c b/source/Service_Libs/fhss/fhss.c index 511c07aa9855..5bc05a1a29b6 100644 --- a/source/Service_Libs/fhss/fhss.c +++ b/source/Service_Libs/fhss/fhss.c @@ -1123,8 +1123,9 @@ static void fhss_data_tx_done_callback(const fhss_api_t *api, bool waiting_ack, } } -static bool fhss_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, int frame_type) +static bool fhss_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, int frame_type, uint8_t channel) { + (void) channel; fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return false; diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 452c6e177bf4..72f334610857 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -663,7 +663,7 @@ static void fhss_ws_data_tx_done_callback(const fhss_api_t *api, bool waiting_ac } } -static bool fhss_ws_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, int frame_type) +static bool fhss_ws_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, int frame_type, uint8_t channel) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { @@ -687,7 +687,7 @@ static bool fhss_ws_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, fhss_failed_handle_remove(fhss_structure, handle); return false; } - fhss_failed_tx->bad_channel = fhss_structure->rx_channel; + fhss_failed_tx->bad_channel = channel; } else { // Create new failure handle and return true to retransmit fhss_failed_handle_add(fhss_structure, handle, fhss_structure->rx_channel); diff --git a/test/nanostack/unittest/service_libs/fhss/test_fhss.c b/test/nanostack/unittest/service_libs/fhss/test_fhss.c index abb1621afd7c..b4075bf08bf9 100644 --- a/test/nanostack/unittest/service_libs/fhss/test_fhss.c +++ b/test/nanostack/unittest/service_libs/fhss/test_fhss.c @@ -48,6 +48,7 @@ #define DEFAULT_WAITING_ACK false #define DEFAULT_TX_COMPLETED true #define DEFAULT_PHY_MTU_SIZE 255 +#define DEFAULT_BAD_CHANNEL 0 static fhss_api_t fhss_api; static fhss_bs_t bs; @@ -259,12 +260,12 @@ bool test_fhss_check_tx_conditions_callback() enable_fhss_struct(); FHSS.fhss_state = FHSS_SYNCHRONIZED; nsdynmemlib_stub.returnCounter = 1; - FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE); + FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL); if (FHSS.fhss_api->check_tx_conditions(api, DEFAULT_IS_BC_DEST, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_FRAME_LENGTH, DEFAULT_PHY_HEAD_LENGTH, DEFAULT_PHY_TAIL_LENGTH) != false) { return false; } // Second call of TX fail should remove the failed handle from list - FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE); + FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL); // Test failing channel type if (FHSS.fhss_api->check_tx_conditions(api, true, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_FRAME_LENGTH, DEFAULT_PHY_HEAD_LENGTH, DEFAULT_PHY_TAIL_LENGTH) != false) { return false; @@ -377,7 +378,7 @@ bool test_fhss_data_tx_done_callback() // Test removing failed handle nsdynmemlib_stub.returnCounter = 1; - FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE); + FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL); FHSS.fhss_api->data_tx_done(api, true, DEFAULT_TX_COMPLETED, DEFAULT_HANDLE); return true; @@ -388,23 +389,23 @@ bool test_fhss_data_tx_fail_callback() fhss_api_t *api = test_generate_fhss_api(); // Test when FHSS struct not found disable_fhss_struct(); - if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test when FHSS not synchronized enable_fhss_struct(); - if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test when channel retries are disabled FHSS.fhss_state = FHSS_SYNCHRONIZED; FHSS.bs->fhss_configuration.fhss_number_of_channel_retries = 0; - if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test incorrect frame type FHSS.bs->fhss_configuration.fhss_number_of_channel_retries = 1; - if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, FHSS_SYNCH_FRAME) != false) { + if (FHSS.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, FHSS_SYNCH_FRAME, DEFAULT_BAD_CHANNEL) != false) { return false; } diff --git a/test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.c b/test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.c index cb513fee6866..c7125085bf55 100644 --- a/test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.c +++ b/test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.c @@ -45,6 +45,7 @@ #define DEFAULT_TIMESTAMP 0 #define DEFAULT_WAITING_ACK false #define DEFAULT_TX_COMPLETED true +#define DEFAULT_BAD_CHANNEL 0 static fhss_api_t fhss_api; static fhss_ws_t ws; @@ -399,33 +400,33 @@ bool test_fhss_ws_data_tx_fail_callback() fhss_api_t *api = test_generate_fhss_api(); // Test when FHSS struct not found disable_fhss_struct(); - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test when FHSS is unsynchronized enable_fhss_struct(); - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test when not data frame fhss_common_stub.fhss_struct.fhss_state = FHSS_SYNCHRONIZED; - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, FHSS_SYNCH_FRAME) != false) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, FHSS_SYNCH_FRAME, DEFAULT_BAD_CHANNEL) != false) { return false; } // Test adding new failed entry fhss_common_stub.fhss_failed_tx.handle = DEFAULT_HANDLE + 1; fhss_common_stub.fhss_failed_tx.retries_done = 0; - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != true) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != true) { return false; } // Test when handle failed again fhss_common_stub.fhss_failed_tx.handle = DEFAULT_HANDLE; - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != true) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != true) { return false; } // Test last failure fhss_common_stub.fhss_failed_tx.retries_done = 3; - if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE) != false) { + if (fhss_common_stub.fhss_struct.fhss_api->data_tx_fail(api, DEFAULT_HANDLE, DEFAULT_FRAME_TYPE, DEFAULT_BAD_CHANNEL) != false) { return false; } diff --git a/test/nanostack/unittest/stub/fhss_config_stub.c b/test/nanostack/unittest/stub/fhss_config_stub.c index b3a32e911da3..765635a82a8a 100644 --- a/test/nanostack/unittest/stub/fhss_config_stub.c +++ b/test/nanostack/unittest/stub/fhss_config_stub.c @@ -44,7 +44,7 @@ void fhss_data_tx_done_cb_stub(const fhss_api_t *api, bool waiting_ack, bool tx_ fhss_config_stub.int8_value++; } -bool fhss_data_tx_fail_cb_stub(const fhss_api_t *api, uint8_t handle, int frame_type) +bool fhss_data_tx_fail_cb_stub(const fhss_api_t *api, uint8_t handle, int frame_type, uint8_t channel) { fhss_config_stub.int8_value++; return true; diff --git a/test/nanostack/unittest/stub/fhss_config_stub.h b/test/nanostack/unittest/stub/fhss_config_stub.h index 21fa2530d6b1..50e29701e0a2 100644 --- a/test/nanostack/unittest/stub/fhss_config_stub.h +++ b/test/nanostack/unittest/stub/fhss_config_stub.h @@ -35,7 +35,7 @@ bool fhss_is_broadcast_channel_cb_stub(const fhss_api_t *api); bool fhss_use_broadcast_queue_cb_stub(const fhss_api_t *api, bool is_broadcast_addr, int frame_type); void fhss_receive_frame_cb_stub(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type); void fhss_data_tx_done_cb_stub(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle); -bool fhss_data_tx_fail_cb_stub(const fhss_api_t *api, uint8_t handle, int frame_type); +bool fhss_data_tx_fail_cb_stub(const fhss_api_t *api, uint8_t handle, int frame_type, uint8_t channel); void fhss_synch_state_set_cb_stub(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); uint32_t fhss_read_timestamp_cb_stub(const fhss_api_t *api); uint16_t fhss_get_retry_period_cb_stub(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu); From c65292e9ebf0d3696a68ce3732e3eb9ce7634ead Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 19 Dec 2019 15:23:55 +0200 Subject: [PATCH 32/88] Mac enhanced ACK pending update Earlier we checked at CCA prepare Neighbour list for new neighbour. New solution will add permission when neighbour is added to list which reduce tx drifting. Change-Id: I9a237e936ea8d3dc538302ff5bec5e4810a2e6e4 --- source/MAC/IEEE802_15_4/mac_pd_sap.c | 2 +- source/MAC/IEEE802_15_4/mac_security_mib.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index a0371a47fb35..85c257f80c14 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -429,7 +429,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r if (rf_ptr->mac_ack_tx_active) { //Accept direct non crypted acks and crypted only if neighbor is at list - if (rf_ptr->ack_tx_possible || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) { + if (rf_ptr->ack_tx_possible) { return PHY_TX_ALLOWED; } diff --git a/source/MAC/IEEE802_15_4/mac_security_mib.c b/source/MAC/IEEE802_15_4/mac_security_mib.c index 8b22875a96da..27de7e89cbee 100644 --- a/source/MAC/IEEE802_15_4/mac_security_mib.c +++ b/source/MAC/IEEE802_15_4/mac_security_mib.c @@ -281,6 +281,7 @@ int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_de return -1; } + platform_enter_critical(); mlme_device_descriptor_t *device_ptr = rf_mac_setup->device_description_table + atribute_index; //Copy description @@ -293,6 +294,24 @@ int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_de //tr_debug("Set %u, mac16 %x mac64: %s, %"PRIu32, atribute_index, device_descriptor->ShortAddress, trace_array(device_descriptor->ExtAddress, 8), device_descriptor->FrameCounter); *device_ptr = *device_descriptor; + + if (rf_mac_setup->mac_ack_tx_active && !rf_mac_setup->ack_tx_possible && + device_ptr->PANId == rf_mac_setup->enhanced_ack_buffer.DstPANId) { + + //Compare address for pending neigbour add + if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) { + uint16_t short_id = common_read_16_bit(rf_mac_setup->enhanced_ack_buffer.DstAddr); + if (short_id == device_ptr->ShortAddress) { + rf_mac_setup->ack_tx_possible = true; + } + } else if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_64_BIT) { + if (memcmp(device_ptr->ExtAddress, rf_mac_setup->enhanced_ack_buffer.DstAddr, 8) == 0) { + rf_mac_setup->ack_tx_possible = true; + } + } + } + platform_exit_critical(); + return 0; } From 46aa46042d36e25b0782b5c57fb4fab097318c59 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 19 Dec 2019 16:08:51 +0200 Subject: [PATCH 33/88] Fixed unit test's. Change-Id: I59ce546c53909c2b5a2cf03bb86f94cc41320c30 --- test/nanostack/unittest/mac/mac_pd_sap/test_mac_pd_sap.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/nanostack/unittest/mac/mac_pd_sap/test_mac_pd_sap.c b/test/nanostack/unittest/mac/mac_pd_sap/test_mac_pd_sap.c index f13eafa53bf9..713fcfc5a73c 100644 --- a/test/nanostack/unittest/mac/mac_pd_sap/test_mac_pd_sap.c +++ b/test/nanostack/unittest/mac/mac_pd_sap/test_mac_pd_sap.c @@ -831,14 +831,6 @@ bool test_mac_cca_prepare_cb() rf_ptr.ack_tx_possible = false; rf_ptr.enhanced_ack_handler_timestamp = 10; - mlme_device_descriptor_t test_neigh; - mac_security_mib_stub.device_ptr = &test_neigh; - - ret = mac_pd_sap_data_cb(&rf_ptr, &phy_message); - if (ret != 0) { - return false; - } - mac_security_mib_stub.device_ptr = NULL; ret = mac_pd_sap_data_cb(&rf_ptr, &phy_message); if (ret != -1 || rf_ptr.mac_ack_tx_active) { From 1d6ce9c0a43b121d6ba827b85b875ed5439455f0 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 3 Dec 2019 13:30:58 +0200 Subject: [PATCH 34/88] DHCPv6 Server feature update Wi-sun border router disable dhcpv6 non autonoumous mode. Added possibility for skip alloacted address storing. Optimized Allocated address entry RAM usage 14 bytes. Server will now support 16-bit address id allocaing and it 64-bit suffics is genated by adding 48-bit padding which is genertaed from server unique link ID + 16-bit allocated id. Change-Id: I958a655a96fefd14ce75315b7149d8800ca7e9f8 --- source/6LoWPAN/Thread/thread_management_if.c | 2 +- source/6LoWPAN/ws/ws_bbr_api.c | 2 +- source/DHCPv6_Server/DHCPv6_Server_service.c | 67 ++-- source/DHCPv6_Server/DHCPv6_server_service.h | 3 +- source/libDHCPv6/libDHCPv6_server.c | 329 ++++++++++++++---- source/libDHCPv6/libDHCPv6_server.h | 49 ++- .../stub/dhcpv6_server_service_stub.c | 2 +- .../unittest/stub/libDHCPv6_server_stub.c | 11 +- 8 files changed, 343 insertions(+), 122 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_management_if.c b/source/6LoWPAN/Thread/thread_management_if.c index 435ab5133458..7409f53a9078 100644 --- a/source/6LoWPAN/Thread/thread_management_if.c +++ b/source/6LoWPAN/Thread/thread_management_if.c @@ -699,7 +699,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t * return -1; } - return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous); + return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous, false); #else (void) interface_id; (void) prefix_ptr; diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index ae778d6711f0..43d5a21fc8f8 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -319,7 +319,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8 } DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb); - DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true); + DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, false, false); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME); ws_dhcp_client_address_request(cur, global_id, ll); diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index c2f567e40f76..a7755034a9df 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -87,7 +87,7 @@ static void DHCP_server_service_timer_stop(void) int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_reply_packet_s *replyPacket, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, dhcpv6_gua_response_t *response, bool allocateNew) { - dhcpv6_alloacted_address_entry_t *dhcp_allocated_address = NULL; + dhcpv6_allocated_address_t *dhcp_allocated_address = NULL; dhcpv6_ia_non_temporal_address_s nonTemporalAddress; bool address_allocated = false; //Validate Client DUID @@ -279,12 +279,15 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], { dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); if (serverInfo) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { //Delete Server data base if (serverInfo->removeCb) { - serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL); + uint8_t allocated_address[16]; + libdhcpv6_allocated_address_write(allocated_address, cur, serverInfo); + serverInfo->removeCb(interface, allocated_address, NULL); } } + if (serverInfo->removeCb) { // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix); @@ -312,18 +315,22 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { - int retVal = -1; - dhcpv6_gua_server_entry_s *serverInfo; + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->enableAddressAutonous = mode; - retVal = 0; } - return retVal; + serverInfo->enableAddressAutonous = mode; + if (mode) { + serverInfo->disableAddressListAllocation = autonomous_skip_list; + } else { + serverInfo->disableAddressListAllocation = false; + } + + return 0; } void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb) @@ -365,18 +372,18 @@ int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static */ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) { - int retVal = -1; dhcpv6_gua_server_entry_s *serverInfo; - if (maxClientCount == 0) { + if (maxClientCount == 0 || maxClientCount > MAX_SUPPORTED_ADDRESS_LIST_SIZE) { return -2; - } else { - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->maxSuppertedClients = maxClientCount; - retVal = 0; - } } - return retVal; + serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + + serverInfo->maxSupportedClients = maxClientCount; + + return 0; } /** SET Address Valid Lifetime parameter for allocated address, Default is 7200 seconds @@ -388,18 +395,17 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ */ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne) { - int retVal = -1; dhcpv6_gua_server_entry_s *serverInfo; if (validLifeTimne < 120) { - retVal = -2; - } else { - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->validLifetime = validLifeTimne; - retVal = 0; - } + return -2; } - return retVal; + serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + serverInfo->validLifetime = validLifeTimne; + + return 0; } #else @@ -422,11 +428,12 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) { (void) timeUpdateInSeconds; } -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { (void) interface; (void) guaPrefix; (void) mode; + (void) autonomous_skip_list; return -1; } diff --git a/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 2a236ad25422..8f8616f4f41d 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/source/DHCPv6_Server/DHCPv6_server_service.h @@ -66,8 +66,9 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); * /param interface interface id of this thread instance. * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id + * /param autonomous_skip_list true skip address list allocation when autonous mode is selected */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode); +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list); /* SET max accepted clients to server, Default is 200 diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index 2f19eb70a4e5..df8a72cb9141 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -49,17 +49,80 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) } entry->serverDynamic_DUID = server_duid_ptr; entry->serverDynamic_DUID_length = 16; - entry->clientIdSequence = 0; + entry->firstFreedId = 0; + entry->firstUnusedId = DHCP_ADDRESS_ID_START; entry->enableAddressAutonous = true; - entry->clientIdDefaultSuffics = 0x0000000; - entry->maxSuppertedClients = 200; + entry->disableAddressListAllocation = false; + entry->maxSupportedClients = 200; entry->validLifetime = 7200; entry->removeCb = NULL; entry->addCb = NULL; ns_list_init(&entry->allocatedAddressList); return entry; } -static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_alloacted_address_entry_t *entry) + +static uint16_t libdhcpv6_get_next_freed_id(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t last_allocated_id = DHCP_ADDRESS_ID_START - 1; + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + + if (last_allocated_id + 1 == cur->allocatedID) { + //Last and current plus 1 so normal order + last_allocated_id = cur->allocatedID; + continue; + } + + if ((cur->allocatedID - last_allocated_id) == 2) { + //one missing sequence between last and current + if (last_allocated_id + 1 == serverInfo->firstFreedId) { + //Skip + continue; + } + } else if (last_allocated_id + 1 == serverInfo->firstFreedId) { + //Skip first if it is last freedId + return last_allocated_id + 2; + } + + return last_allocated_id + 1; + } + //No more freed ID so return 0 + return 0; +} + +static uint16_t libdhcpv6_address_id_allocate(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t address_id; + if (serverInfo->firstFreedId) { + address_id = serverInfo->firstFreedId; + //Discover next free freed possible value + serverInfo->firstFreedId = libdhcpv6_get_next_freed_id(serverInfo); + } else { + //Allocated new ID + address_id = serverInfo->firstUnusedId++; + } + return address_id; +} + +static void libdhcpv6_gen_suffics_from_eui48(uint8_t *ptr, uint8_t *eui48) +{ + *ptr++ = *eui48++ ^ 2; + *ptr++ = *eui48++; + *ptr++ = *eui48++; + *ptr++ = 0xff; + *ptr++ = 0xfe; + *ptr++ = *eui48++; + *ptr++ = *eui48++; + *ptr = *eui48++; +} + +static void libdhcpv6_gen_suffics_from_allocated_id(uint8_t *ptr, uint8_t *server_unique_48_bit_id, uint16_t allocated_id) +{ + memcpy(ptr, server_unique_48_bit_id, 6); + common_write_16_bit(allocated_id, ptr + 6); +} + + +static uint16_t libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_t *entry) { //GENERATE ADDRESS uint8_t *ptr = entry->nonTemporalAddress; @@ -70,25 +133,78 @@ static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dh entry->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { memcpy(ptr, entry->linkId, 8); *ptr ^= 2; - } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { - *ptr++ = entry->linkId[0] ^ 2; - *ptr++ = entry->linkId[1]; - *ptr++ = entry->linkId[2]; - *ptr++ = 0xff; - *ptr++ = 0xfe; - *ptr++ = entry->linkId[3]; - *ptr++ = entry->linkId[4]; - *ptr = entry->linkId[5]; - } else { - ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); - ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); + return 0; } - } else { - ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); - ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); + if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(ptr, entry->linkId); + return 0; + } + } + + uint16_t allocated_id = libdhcpv6_address_id_allocate(serverInfo); + libdhcpv6_gen_suffics_from_allocated_id(ptr, serverInfo->clientIdDefaultSuffics, allocated_id); + return allocated_id; +} + +static void libdhcpv6_address_free(dhcpv6_gua_server_entry_s *server_info, dhcpv6_allocated_address_entry_t *entry) +{ + ns_list_remove(&server_info->allocatedAddressList, entry); + if (!server_info->enableAddressAutonous) { + if (entry->allocatedID + 1 == server_info->firstUnusedId) { + server_info->firstUnusedId--; + } else if (server_info->firstFreedId == 0 || server_info->firstFreedId > entry->allocatedID) { + server_info->firstFreedId = entry->allocatedID; + } + } + ns_dyn_mem_free(entry); +} + +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + memcpy(ptr, serverInfo->guaPrefix, 8); + ptr += 8; + if (serverInfo->enableAddressAutonous) { + //Generate address from link layer address + if (address->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || + address->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { + memcpy(ptr, address->linkId, 8); + *ptr ^= 2; + return; + } else if (address->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(ptr, address->linkId); + return; + } } - serverInfo->clientIdSequence++; + //Generate from 16-bit allocate and default suffic's + libdhcpv6_gen_suffics_from_allocated_id(ptr, serverInfo->clientIdDefaultSuffics, address->allocatedID); +} + +static bool libdhcpv6_address_suffics_compare(const uint8_t *suffics, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + uint8_t allocated_suffics[8]; + if (serverInfo->enableAddressAutonous) { + //Generate address from link layer address + if (address->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || + address->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { + memcpy(allocated_suffics, address->linkId, 8); + allocated_suffics[0] ^= 2; + goto compare_suffics; + } else if (address->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(allocated_suffics, address->linkId); + goto compare_suffics; + } + } + //Generate from 16-bit allocate and default suffic's + libdhcpv6_gen_suffics_from_allocated_id(allocated_suffics, serverInfo->clientIdDefaultSuffics, address->allocatedID); + +compare_suffics: + if (memcmp(allocated_suffics, suffics, 8)) { + return false; + } + + return true; + } @@ -97,15 +213,16 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) //Check All allocated server inside this loop ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) { //Check All allocated address in this module - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, address, &cur->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, address, &cur->allocatedAddressList) { //Update if (address->preferredLifetime) { if (address->preferredLifetime <= timeUpdateInSeconds) { //Stop use this address for leasequery and delete Route or address map - address->preferredLifetime = 0; if (cur->removeCb) { - cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix); + uint8_t allocated_address[16]; + libdhcpv6_allocated_address_write(allocated_address, address, cur); + cur->removeCb(cur->interfaceId, allocated_address, cur->guaPrefix); } } else { address->preferredLifetime -= timeUpdateInSeconds; @@ -113,8 +230,7 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) } if (address->lifetime <= timeUpdateInSeconds) { - ns_list_remove(&cur->allocatedAddressList, address); - ns_dyn_mem_free(address); + libdhcpv6_address_free(cur, address); } else { address->lifetime -= timeUpdateInSeconds; } @@ -187,6 +303,15 @@ dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t duid_length = libdhcpv6_duid_linktype_size(serverDUIDType) + 2; ptr = common_write_16_bit(serverDUIDType, ptr); memcpy(ptr, serverDUID, libdhcpv6_duid_linktype_size(serverDUIDType)); + //SET Defaultsuffics + if (libdhcpv6_duid_linktype_size(serverDUIDType) == 8) { + memcpy(entry->clientIdDefaultSuffics, serverDUID, 3); + memcpy(entry->clientIdDefaultSuffics + 3, serverDUID + 5, 3); + } else { + memcpy(entry->clientIdDefaultSuffics, serverDUID, 6); + } + + entry->clientIdDefaultSuffics[0] ^= 0x02; //SET DUID if (libdhcpv6_server_duid_set(entry, duid_ll, DHCPV6_DUID_LINK_LAYER_TYPE, duid_length) != 0) { @@ -208,7 +333,7 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); if (serverInfo) { if ((serverInfo->interfaceId == interfaceId) && (memcmp(serverInfo->guaPrefix, prefix, 8) == 0)) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { ns_list_remove(&serverInfo->allocatedAddressList, cur); ns_dyn_mem_free(cur); } @@ -219,26 +344,52 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t } } -static dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) +static void libdhcpv6_address_entry_lifetime_set(dhcpv6_allocated_address_entry_t *entry, uint32_t validLifetime) { - dhcpv6_alloacted_address_entry_t *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_alloacted_address_entry_t)); - if (entry) { - if (validLifetime != 0xffffffff) { - entry->lifetime = validLifetime; - entry->preferredLifetime = (validLifetime >> 1); - } else { - entry->lifetime = 0xffffffff; - entry->preferredLifetime = 0xffffffff; - } + if (validLifetime != 0xffffffff) { + entry->lifetime = validLifetime; + entry->preferredLifetime = (validLifetime >> 1); + } else { + entry->lifetime = 0xffffffff; + entry->preferredLifetime = 0xffffffff; } - return entry; } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +static void libdhcpv6_copy_allocated_entry_to_temp(dhcpv6_allocated_address_entry_t *cur, dhcpv6_allocated_address_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + libdhcpv6_allocated_address_write(address->nonTemporalAddress, cur, serverInfo); + memcpy(address->linkId, cur->linkId, 8); + address->T0 = cur->T0; + address->T1 = cur->T1; + address->iaID = cur->iaID; + address->lifetime = cur->lifetime; + address->preferredLifetime = cur->preferredLifetime; + address->linkType = cur->linkType; +} + + +static void libdhcpv6_copy_temp_to_allocated_entry(dhcpv6_allocated_address_entry_t *cur, dhcpv6_allocated_address_t *address, uint16_t allocated_id) +{ + memcpy(cur->linkId, address->linkId, 8); + cur->allocatedID = allocated_id; + cur->T0 = address->T0; + cur->T1 = address->T1; + cur->iaID = address->iaID; + cur->lifetime = address->lifetime; + cur->preferredLifetime = address->preferredLifetime; + cur->linkType = address->linkType; +} + +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { - ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { - return cur; + if (memcmp(serverInfo->guaPrefix, address, 8)) { + return NULL; + } + + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (libdhcpv6_address_suffics_compare(address + 8, cur, serverInfo) == 0) { + libdhcpv6_copy_allocated_entry_to_temp(cur, &serverInfo->tempAddressEntry, serverInfo); + return &serverInfo->tempAddressEntry; } } return NULL; @@ -246,49 +397,95 @@ dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcp void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { - ns_list_remove(&serverInfo->allocatedAddressList, cur); - ns_dyn_mem_free(cur); + if (memcmp(serverInfo->guaPrefix, address, 8)) { + return; + } + + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (libdhcpv6_address_suffics_compare(address + 8, cur, serverInfo) == 0) { + libdhcpv6_address_free(serverInfo, cur); return; } } } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) + +static void libdhcpv6_address_id_add_to_list(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_entry_t *allocated) +{ + if (serverInfo->firstUnusedId != allocated->allocatedID + 1) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (cur->allocatedID > allocated->allocatedID) { + //Add before new allocated + if (cur->link.prev) { + ns_list_add_before(&serverInfo->allocatedAddressList, cur, allocated); + } else { + //New first + ns_list_add_to_start(&serverInfo->allocatedAddressList, allocated); + } + return; + } + } + } + ns_list_add_to_end(&serverInfo->allocatedAddressList, allocated); +} + + +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) { - dhcpv6_alloacted_address_entry_t *newEntry = NULL; + dhcpv6_allocated_address_t *newEntry = NULL; + dhcpv6_allocated_address_entry_t *allocatedEntry = NULL; uint16_t duiLength = 6; if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { duiLength = 8; } - ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + + if (serverInfo->enableAddressAutonous && serverInfo->disableAddressListAllocation) { + //Accept allways when autonous + newEntry = &serverInfo->tempAddressEntry; + allocateNew = false; + } + + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { if (cur->linkType == linkType) { if (memcmp(cur->linkId, linkId, duiLength) == 0) { cur->iaID = iaID; - if (serverInfo->validLifetime != 0xffffffff) { - cur->lifetime = serverInfo->validLifetime ; - cur->preferredLifetime = (serverInfo->validLifetime >> 1); - } else { - cur->lifetime = 0xffffffff; - cur->preferredLifetime = 0xffffffff; - } - return cur; + libdhcpv6_address_entry_lifetime_set(cur, serverInfo->validLifetime); + libdhcpv6_copy_allocated_entry_to_temp(cur, &serverInfo->tempAddressEntry, serverInfo); + return &serverInfo->tempAddressEntry; } } } if (allocateNew) { - if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSuppertedClients) { - newEntry = libdhcpv6_address_entry_allocate(serverInfo->validLifetime); - if (newEntry) { - memcpy(newEntry->linkId, linkId, duiLength); - newEntry->linkType = linkType; - newEntry->iaID = iaID; - newEntry->T0 = T0; - newEntry->T1 = T1; - libdhcpv6_address_generate(serverInfo, newEntry); - ns_list_add_to_end(&serverInfo->allocatedAddressList, newEntry); + if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSupportedClients) { + allocatedEntry = ns_dyn_mem_alloc(sizeof(dhcpv6_allocated_address_entry_t)); + if (allocatedEntry) { + newEntry = &serverInfo->tempAddressEntry; + } + } + } + if (newEntry) { + + if (serverInfo->validLifetime != 0xffffffff) { + newEntry->lifetime = serverInfo->validLifetime; + newEntry->preferredLifetime = (serverInfo->validLifetime >> 1); + } else { + newEntry->lifetime = 0xffffffff; + newEntry->preferredLifetime = 0xffffffff; + } + memcpy(newEntry->linkId, linkId, duiLength); + newEntry->linkType = linkType; + newEntry->iaID = iaID; + newEntry->T0 = T0; + newEntry->T1 = T1; + uint16_t allocated_id = libdhcpv6_address_generate(serverInfo, newEntry); + if (!serverInfo->disableAddressListAllocation) { + libdhcpv6_copy_temp_to_allocated_entry(allocatedEntry, newEntry, allocated_id); + if (serverInfo->enableAddressAutonous) { + ns_list_add_to_end(&serverInfo->allocatedAddressList, allocatedEntry); + } else { + //Add to list to proper order + libdhcpv6_address_id_add_to_list(serverInfo, allocatedEntry); } } } diff --git a/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index ba17b340f5d7..3b4c0643e2e5 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/source/libDHCPv6/libDHCPv6_server.h @@ -28,29 +28,36 @@ #include "libDHCPv6/libDHCPv6.h" +#define MAX_SUPPORTED_ADDRESS_LIST_SIZE 0x0000fffd +#define DHCP_ADDRESS_ID_START 2 + typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info); -typedef struct dhcpv6_alloacted_address_entry_s { - uint8_t nonTemporalAddress[16]; +typedef struct dhcpv6_allocated_address_entry_s { uint8_t linkId[8]; /*!< Services UL64 */ - uint16_t linkType; uint32_t iaID; uint32_t T0; uint32_t T1; uint32_t preferredLifetime; uint32_t lifetime; + uint16_t linkType; + uint16_t allocatedID; ns_list_link_t link; /*!< List link entry */ -} dhcpv6_alloacted_address_entry_t; +} dhcpv6_allocated_address_entry_t; -typedef NS_LIST_HEAD(dhcpv6_alloacted_address_entry_t, link) dhcpv6_alloacted_address_list_t; -typedef struct thread_dhcpv6_server_data_s { - uint8_t prefix[8]; /*!< Services Prefix */ - uint16_t maxSuppertedClients; - uint32_t clientIdSequence; /*!< Define */ - dhcpv6_alloacted_address_list_t allocatedAddressList; - ns_list_link_t link; /*!< List link entry */ -} dhcpv6_server_data_entry_t; +typedef struct dhcpv6_allocated_address_s { + uint8_t nonTemporalAddress[16]; + uint8_t linkId[8]; /*!< Services UL64 */ + uint16_t linkType; + uint32_t iaID; + uint32_t T0; + uint32_t T1; + uint32_t preferredLifetime; + uint32_t lifetime; +} dhcpv6_allocated_address_t; + +typedef NS_LIST_HEAD(dhcpv6_allocated_address_entry_t, link) dhcpv6_allocated_address_list_t; typedef struct dhcp_address_cache_update { uint8_t *allocatedAddress; @@ -62,19 +69,22 @@ typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache typedef struct dhcpv6_gua_server_entry_s { int8_t interfaceId; - bool enableAddressAutonous; + bool enableAddressAutonous: 1; + bool disableAddressListAllocation: 1; uint16_t socketInstance_id; uint8_t guaPrefix[8]; uint8_t serverDynamic_DUID_length; - uint32_t maxSuppertedClients; - uint32_t clientIdDefaultSuffics; - uint32_t clientIdSequence; /*!< Define */ + uint32_t maxSupportedClients; + uint8_t clientIdDefaultSuffics[6]; + uint16_t firstFreedId; + uint16_t firstUnusedId; /*!< This is first unused Id */ uint32_t validLifetime; dhcp_duid_options_params_t serverDUID; uint8_t *serverDynamic_DUID; dhcp_address_prefer_remove_cb *removeCb; dhcp_address_add_notify_cb *addCb; - dhcpv6_alloacted_address_list_t allocatedAddressList; + dhcpv6_allocated_address_list_t allocatedAddressList; + dhcpv6_allocated_address_t tempAddressEntry; ns_list_link_t link; /*!< List link entry */ } dhcpv6_gua_server_entry_s; @@ -84,10 +94,11 @@ int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *d void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId); void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds); void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(int8_t interfaceId, const uint8_t *prefixPtr); dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr); -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo); #else #define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL diff --git a/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c b/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c index 3cf90d0d8f82..b4439ff91253 100644 --- a/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c +++ b/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c @@ -95,7 +95,7 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { return 0; } diff --git a/test/nanostack/unittest/stub/libDHCPv6_server_stub.c b/test/nanostack/unittest/stub/libDHCPv6_server_stub.c index b7e956b4de7d..a82dfa5c9780 100644 --- a/test/nanostack/unittest/stub/libDHCPv6_server_stub.c +++ b/test/nanostack/unittest/stub/libDHCPv6_server_stub.c @@ -47,12 +47,12 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t { } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) +dhcpv6_allocated_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) { return NULL; } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { return NULL; } @@ -62,7 +62,7 @@ void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverI } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) { return NULL; } @@ -77,3 +77,8 @@ bool libdhcpv6_gua_server_list_empty(void) return true; } +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + +} + From eabca172af47f0f62da8eed1c2f4d9d1bc0b6bc6 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 8 Jan 2020 10:16:08 +0200 Subject: [PATCH 35/88] Wi-Sun Border router DHCPV server SLAAC mode enabled by default. Change-Id: Ie7ca9a6cd264b3cec813430186778c1d2349593f --- source/6LoWPAN/ws/ws_bbr_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 43d5a21fc8f8..4dfe7bb14df8 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -318,8 +318,8 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8 return; } DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb); - - DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, false, false); + //Enable SLAAC mode to border router + DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME); ws_dhcp_client_address_request(cur, global_id, ll); From 11c486f391472fd3e1cdd150480d01d74f9714f2 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 9 Jan 2020 16:10:20 +0200 Subject: [PATCH 36/88] Implemented unregistering FHSS from MAC. FHSS deleted in ifdown call. (#2266) --- nanostack/sw_mac.h | 7 +++++++ source/6LoWPAN/ws/ws_bootstrap.c | 27 +++++++------------------- source/6LoWPAN/ws/ws_common.h | 1 - source/MAC/IEEE802_15_4/sw_mac.c | 14 +++++++++++++ source/Service_Libs/fhss/fhss_common.c | 2 ++ source/Service_Libs/fhss/fhss_ws.c | 8 +++++++- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/nanostack/sw_mac.h b/nanostack/sw_mac.h index e4a018fc4e90..894b8b75c4bd 100644 --- a/nanostack/sw_mac.h +++ b/nanostack/sw_mac.h @@ -67,6 +67,13 @@ extern int8_t ns_sw_mac_virtual_client_unregister(struct mac_api_s *api); */ extern int ns_sw_mac_fhss_register(struct mac_api_s *mac_api, struct fhss_api *fhss_api); +/** + * @brief Unregister FHSS API instance from given software MAC instance. + * @param mac_api MAC instance. + * @return 0 on success, -1 on fail. + */ +extern int ns_sw_mac_fhss_unregister(struct mac_api_s *mac_api); + /** * @brief Request registered FHSS API instance from software MAC instance. * @param mac_api MAC instance. diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 71dca085899d..2d5c029fbd00 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -423,8 +423,7 @@ static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur) { fhss_api_t *fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); - - if (!fhss_api || (fhss_api && cur->ws_info->fhss_owner)) { + if (!fhss_api) { // When FHSS doesn't exist yet, create one fhss_ws_configuration_t fhss_configuration; memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); @@ -440,26 +439,11 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur) fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_bc_channel_function; fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval; fhss_configuration.fhss_broadcast_interval = cur->ws_info->fhss_bc_interval; - + fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); if (!fhss_api) { - fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); - if (!fhss_api) { - tr_error("fhss create failed"); - return -1; - } - ns_sw_mac_fhss_register(cur->mac_api, fhss_api); - cur->ws_info->fhss_owner = true; - } else { - //Configuration set - ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); - - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0); - } else { - //Clear OWN HOP - ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff); - } + return -1; } + ns_sw_mac_fhss_register(cur->mac_api, fhss_api); } else { // Read defaults from the configuration to help FHSS testing const fhss_ws_configuration_t *fhss_configuration = ns_fhss_ws_configuration_get(fhss_api); @@ -810,6 +794,9 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) tr_info("Wi-SUN ifdown"); // Reset MAC for safe upper layer memory free protocol_mac_reset(cur); + ns_sw_mac_fhss_unregister(cur->mac_api); + ns_fhss_delete(cur->ws_info->fhss_api); + cur->ws_info->fhss_api = NULL; // Reset WS information // ws_common_reset(cur) ws_llc_reset(cur); diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 4fae3664f93d..d8929df5a98e 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -97,7 +97,6 @@ typedef struct ws_info_s { bool trickle_pa_running: 1; bool trickle_pcs_running: 1; bool trickle_pc_running: 1; - bool fhss_owner: 1; ws_pending_key_index_t pending_key_index_info; // default fhss parameters for this device uint8_t fhss_uc_dwell_interval; diff --git a/source/MAC/IEEE802_15_4/sw_mac.c b/source/MAC/IEEE802_15_4/sw_mac.c index ca52231bac21..a5b679eb2845 100644 --- a/source/MAC/IEEE802_15_4/sw_mac.c +++ b/source/MAC/IEEE802_15_4/sw_mac.c @@ -197,6 +197,20 @@ int ns_sw_mac_fhss_register(mac_api_t *mac_api, fhss_api_t *fhss_api) return 0; } +int ns_sw_mac_fhss_unregister(mac_api_t *mac_api) +{ + if (!mac_api) { + return -1; + } + // Get a pointer to MAC setup structure + protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_mac_api(mac_api); + if (!mac_setup) { + return -1; + } + mac_setup->fhss_api = NULL; + return 0; +} + struct fhss_api *ns_sw_mac_get_fhss_api(struct mac_api_s *mac_api) { if (!mac_api) { diff --git a/source/Service_Libs/fhss/fhss_common.c b/source/Service_Libs/fhss/fhss_common.c index d2826ca7e85d..25cd4b8b821d 100644 --- a/source/Service_Libs/fhss/fhss_common.c +++ b/source/Service_Libs/fhss/fhss_common.c @@ -113,6 +113,8 @@ int8_t fhss_disable(fhss_structure_t *fhss_structure) } fhss_structure->fhss_api->synch_state_set(fhss_structure->fhss_api, FHSS_UNSYNCHRONIZED, 0); ns_dyn_mem_free(fhss_structure->bs); + ns_dyn_mem_free(fhss_structure->ws->tr51_channel_table); + ns_dyn_mem_free(fhss_structure->ws->tr51_output_table); ns_dyn_mem_free(fhss_structure->ws); ns_dyn_mem_free(fhss_structure); fhss_struct = 0; diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 72f334610857..d8c07b8a738f 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -305,8 +305,11 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) { (void) slots; uint16_t queue_size = 0; - fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); + fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); + if (!fhss_structure) { + return; + } if (fhss_structure->ws->is_on_bc_channel == true) { queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true); @@ -407,6 +410,9 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat } } else if (fhss_state == FHSS_UNSYNCHRONIZED) { fhss_structure->ws->synchronization_time = 0; + eventOS_callback_timer_stop(fhss_structure->fhss_event_timer); + fhss_stop_timer(fhss_structure, fhss_unicast_handler); + fhss_stop_timer(fhss_structure, fhss_broadcast_handler); } fhss_structure->fhss_state = fhss_state; From ac335184939b9395f10a4e675070879fcd1d0474 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 9 Jan 2020 11:06:56 +0200 Subject: [PATCH 37/88] Wi-sun ETX and proping update Removed Accelaterd Probe feature to child address registration. ETX support now dynamic init sampling count. ETX local read return configured MAX value for neighbour when no ETX sample have been done. Change-Id: I2a59b7bb52b52a24a87c9c956d252726703a275a --- source/6LoWPAN/ND/nd_router_object.c | 3 - source/6LoWPAN/ws/ws_bootstrap.c | 98 ++++--------------- source/6LoWPAN/ws/ws_bootstrap.h | 3 - source/6LoWPAN/ws/ws_common.c | 11 --- source/6LoWPAN/ws/ws_common.h | 3 - source/6LoWPAN/ws/ws_common_defines.h | 4 +- source/6LoWPAN/ws/ws_neighbor_class.h | 1 - source/Service_Libs/etx/etx.c | 83 ++++++++++++---- source/Service_Libs/etx/etx.h | 13 ++- test/nanostack/unittest/stub/etx_stub.c | 2 +- .../unittest/stub/ws_bootstrap_stub.c | 5 - test/nanostack/unittest/stub/ws_common_stub.c | 5 - 12 files changed, 99 insertions(+), 132 deletions(-) diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index c397bfa66c83..41a051816cc2 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -856,9 +856,6 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh), ADDR_802_15_4_LONG); if (entry) { - if (ws_info(cur_interface)) { - ws_common_etx_validate(cur_interface, entry); - } if (!entry->ffd_device) { rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime); diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 2d5c029fbd00..3474f0aecb43 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -663,33 +663,8 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr ws_neighbor_class_entry_t *ws_neighbour = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, attribute_index); etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, attribute_index); - if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - if (!ws_neighbour || !etx_entry) { - return 0xffff; - } - } else { - - if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 /*|| - !ws_neighbour->candidate_parent*/) { - // if RSL value is not good enough candidate parent flag is removed and device not accepted as parent - //tr_debug("ws_etx_read not valid params"); - return 0xffff; - } - - //If we are not following gbobal Broadcast synch - if (!interface->ws_info->pan_information.use_parent_bs) { - //We must know both information's here - if (!ws_neighbour->broadcast_shedule_info_stored || - !ws_neighbour->broadcast_timing_info_stored) { - return 0xffff; - } - } else { - if (!ws_neighbour->broadcast_timing_info_stored) { - //Global shedule is stored already - tr_debug("ws_etx_read not valid NO BTI"); - return 0xffff; - } - } + if (!ws_neighbour || !etx_entry) { + return 0xffff; } etx = etx_local_etx_read(interface->id, attribute_index); @@ -1497,7 +1472,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent continue; } - if (cur->nud_active || ws_neighbor->accelerated_etx_probe || ws_neighbor->negative_aro_send) { + if (cur->nud_active || ws_neighbor->negative_aro_send) { //If NUD process is active do not trig continue; } @@ -1657,34 +1632,28 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, } } nud_proces = activate_nud; - } else if (etx_entry->etx_samples < WS_NEIGBOR_ETX_SAMPLE_MAX) { + } else if (etx_entry->etx_samples < WS_NEIGHBOR_ETX_SAMPLE_MAX) { //Take Random number for trig a prope. //ETX Sample 0: random 1-8 //ETX Sample 1: random 2-16 //ETX Sample 2: random 4-32 - if (etx_entry->etx_samples == 0 && ws_neighbor->accelerated_etx_probe) { - //Accept quick Probe for init ETX - activate_nud = true; - } else { - - ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); - if (!rpl_control_probe_parent_candidate(cur, ll_address)) { - return false; - } + ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); + if (!rpl_control_probe_parent_candidate(cur, ll_address)) { + return false; + } - uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples; - uint32_t time_block = 1 << etx_entry->etx_samples; - if (time_from_start >= probe_period) { - //tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples); + uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples; + uint32_t time_block = 1 << etx_entry->etx_samples; + if (time_from_start >= probe_period) { + //tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples); + activate_nud = true; + } else if (time_from_start > time_block) { + uint16_t switch_prob = randLIB_get_random_in_range(0, probe_period - 1); + //Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5 + if (switch_prob < 2) { + //tr_debug("Link Probe test with jitter %"PRIu32", sample %u", time_from_start, etx_entry->etx_samples); activate_nud = true; - } else if (time_from_start > time_block) { - uint16_t switch_prob = randLIB_get_random_in_range(0, probe_period - 1); - //Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5 - if (switch_prob < 2) { - //tr_debug("Link Probe test with jitter %"PRIu32", sample %u", time_from_start, etx_entry->etx_samples); - activate_nud = true; - } } } } @@ -1698,10 +1667,6 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, return false; } entry->neighbor_info = entry_ptr; - if (ws_neighbor->accelerated_etx_probe) { - ws_neighbor->accelerated_etx_probe = false; - entry->timer = 1; - } entry->nud_process = nud_proces; @@ -1737,12 +1702,13 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) { return -1; } - if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT)) { + if (!etx_cached_etx_parameter_set(WS_ETX_MIN_WAIT_TIME, WS_ETX_MIN_SAMPLE_COUNT, WS_NEIGHBOR_FIRST_ETX_SAMPLE_MIN_COUNT)) { etx_storage_list_allocate(cur->id, 0); return -1; } etx_max_update_set(WS_ETX_MAX_UPDATE); + etx_max_set(WS_ETX_MAX); if (blacklist_init() != 0) { tr_err("MLE blacklist init failed."); @@ -2597,10 +2563,7 @@ static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entr if (etx == 0) { etx = 0xffff; } - if (etx > 0x800) { - // Wi-SUN section 6.2.3.1.6.1 says ETX can only be maximum of 1024 (8*128) in RPL units, ie 8.0. - etx = 0x800; - } + //Scale to 128 based ETX (local read retur 0x100 - 0xffff etx = etx >> 1; return ws_neighbor->routing_cost + etx; @@ -3076,23 +3039,4 @@ void ws_secondary_parent_update(protocol_interface_info_entry_t *interface) } } -void ws_bootstrap_etx_accelerate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh) -{ - ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neigh->index); - //Enable Faster ETX probing - ws_neighbor->accelerated_etx_probe = true; - //Move Neighbor to first to for accelerate Process - mac_neighbor_table_t *table_class = mac_neighbor_info(interface); - ns_list_remove(&table_class->neighbour_list, neigh); - ns_list_add_to_start(&table_class->neighbour_list, neigh); - //Try to Generate Active NUD Immediately - if (!ws_neighbor_entry_nud_notify(neigh, interface)) { - return;//Return if NUD active is full - } - table_class->active_nud_process++; - neigh->nud_active = true; - //Push NS to send - ws_nud_active_timer(interface, 0); -} - #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 9d7f55246594..062dc767a3b1 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -76,8 +76,6 @@ bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur); void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info); -void ws_bootstrap_etx_accelerate(struct protocol_interface_info_entry *cur, mac_neighbor_table_entry_t *neigh); - #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) @@ -87,7 +85,6 @@ void ws_bootstrap_etx_accelerate(struct protocol_interface_info_entry *cur, mac_ #define ws_bootstrap_aro_failure(cur, ll_address) #define ws_primary_parent_update(interface, neighbor) #define ws_secondary_parent_update(interface) -#define ws_bootstrap_etx_accelerate(cur, neigh) ((void) 0) #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 92792c393ab6..79a24317e277 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -456,17 +456,6 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con return true; } -void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh) -{ - etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, neigh->index); - - if (neigh->nud_active || !neigh->trusted_device || !etx_entry || etx_entry->etx_samples) { - return; //Do not trig Second NS if Active NUD already, not trusted or ETX samples already done - } - - ws_bootstrap_etx_accelerate(interface, neigh); -} - uint32_t ws_common_version_lifetime_get(uint8_t config) { uint32_t lifetime; diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index d8929df5a98e..5e00e4c322ab 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -142,8 +142,6 @@ void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8 bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64); -void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh); - bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64); @@ -160,7 +158,6 @@ uint32_t ws_common_version_timeout_get(uint8_t config); #define ws_common_neighbor_remove(cur, ll_address) #define ws_common_fast_timer(cur, ticks) ((void) 0) #define ws_common_allow_child_registration(cur, eui64) (false) -#define ws_common_etx_validate(interface, neigh) ((void) 0) #define ws_common_negative_aro_mark(interface, eui64)(false) #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 79398a1a339d..92f7da38eb49 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -190,7 +190,8 @@ typedef struct ws_bs_ie { #define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL 260 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 -#define WS_NEIGBOR_ETX_SAMPLE_MAX 3 +#define WS_NEIGHBOR_ETX_SAMPLE_MAX 3 +#define WS_NEIGHBOR_FIRST_ETX_SAMPLE_MIN_COUNT 3 //This can't be bigger than WS_NEIGHBOR_ETX_SAMPLE_MAX #define WS_NEIGHBOUR_MAX_CANDIDATE_PROBE 5 #define WS_PROBE_INIT_BASE_SECONDS 8 @@ -204,6 +205,7 @@ typedef struct ws_bs_ie { #define WS_ETX_MIN_SAMPLE_COUNT 4 #define WS_ETX_MAX_UPDATE 1024 +#define WS_ETX_MAX 1024 #define WS_ETX_MIN_WAIT_TIME 60 diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index 2a0cbe2c1229..c381b43f50eb 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -32,7 +32,6 @@ typedef struct ws_neighbor_class_entry { bool broadcast_timing_info_stored: 1; bool broadcast_shedule_info_stored: 1; bool synch_done : 1; - bool accelerated_etx_probe : 1; bool negative_aro_send : 1; bool unicast_data_rx : 1; } ws_neighbor_class_entry_t; diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 2f79457555ee..6f3c671dd658 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -62,11 +62,13 @@ typedef struct { etx_storage_t *etx_storage_list; etx_sample_storage_t *etx_cache_storage_list; uint32_t max_etx_update; + uint32_t max_etx; uint16_t hysteresis; // 12 bit fraction uint8_t accum_threshold; uint8_t etx_min_sampling_time; uint8_t ext_storage_list_size; uint8_t min_sample_count; + uint8_t init_etx_sample_count; bool cache_sample_requested; int8_t interface_id; } ext_info_t; @@ -81,6 +83,8 @@ static ext_info_t etx_info = { .ext_storage_list_size = 0, .min_sample_count = 0, .max_etx_update = 0, + .max_etx = 0xffff, + .init_etx_sample_count = 1, .cache_sample_requested = false, .etx_min_sampling_time = 0, .interface_id = -1 @@ -89,7 +93,9 @@ static ext_info_t etx_info = { static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t acks_rx, uint8_t attribute_index) { if (etx_info.hysteresis && !entry->stored_diff_etx) { - entry->stored_diff_etx = entry->etx; + if (entry->etx_samples >= etx_info.init_etx_sample_count) { + entry->stored_diff_etx = entry->etx; + } } uint32_t etx = attempts << (12 - ETX_MOVING_AVERAGE_FRACTION); @@ -99,11 +105,14 @@ static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t ack } else { etx = 0xffff; } + if ((etx_info.max_etx_update) && etx > etx_info.max_etx_update) { etx = etx_info.max_etx_update; } - if (etx_info.cache_sample_requested && entry->etx_samples == 1) { + //tr_debug("Attempts %u ACK %u 1/8 update %u", attempts, acks_rx, etx); + + if (etx_info.cache_sample_requested && entry->etx_samples <= etx_info.init_etx_sample_count) { // skip the initial value as RSSI generated ETX is not valid etx = etx << 3; } else { @@ -111,18 +120,20 @@ static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t ack etx += entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION); } - if (etx > 0xffff) { - etx = 0xffff; + if (etx > etx_info.max_etx) { + etx = etx_info.max_etx; } // If real ETX value has been received do not update based on LQI or dBm entry->tmp_etx = false; - entry->etx = etx; - etx_cache_entry_init(attribute_index); + entry->etx = etx; - // Checks if ETX value change callback is needed - etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index); + if (entry->etx_samples >= etx_info.init_etx_sample_count) { + etx_cache_entry_init(attribute_index); + // Checks if ETX value change callback is needed + etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index); + } } static void etx_cache_entry_init(uint8_t attribute_index) @@ -148,23 +159,23 @@ static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *en } } - if (entry->etx_samples > ETX_ACCELERATED_SAMPLE_COUNT) { + if (entry->etx_samples > etx_info.init_etx_sample_count) { //Slower ETX update phase - if (storage->sample_count < etx_info.min_sample_count || storage->etx_timer) { - if (storage->sample_count < 0xff) { - return false; + if (storage->sample_count >= etx_info.min_sample_count) { + + if (storage->etx_timer == 0 || storage->sample_count == 0xff) { + //Got least min sample in requested time or max possible sample + return true; } } - } else { - //Accelerated ETX at for new neighbor - if (storage->sample_count < ETX_ACCELERATED_INTERVAL) { - return false; - } + return false; } - //tr_debug("ETX update possible %u attempts, %u rx ack", storage->attempts_count, storage->received_acks); + if (time_update == 0) { + return true; + } - return true; + return false; } @@ -212,7 +223,11 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ etx_sample_storage_t *storage = etx_cache_sample_update(attribute_index, attempts, success); entry->accumulated_failures = 0; - if (!entry->etx || (entry->etx_samples > 1 && !etx_update_possible(storage, entry, 0))) { + if (!success && entry->etx_samples < etx_info.init_etx_sample_count) { + storage->sample_count = etx_info.init_etx_sample_count; //Force stop probing if any init fail totally + } + + if (!etx_update_possible(storage, entry, 0)) { return; } @@ -382,6 +397,14 @@ uint16_t etx_local_etx_read(int8_t interface_id, uint8_t attribute_index) if (!entry) { return 0; } + + if (etx_info.cache_sample_requested && entry->etx_samples < etx_info.init_etx_sample_count) { + if (!entry->etx_samples) { + //Return configured MAX value + return etx_info.max_etx >> 4; + } + } + return etx_current_calc(entry->etx, entry->accumulated_failures) >> 4; } @@ -590,7 +613,7 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size) } -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count) +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count) { //No ini ETX allocation done yet if (etx_info.ext_storage_list_size == 0) { @@ -598,6 +621,10 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_ } if (min_wait_time || etx_min_sample_count) { + if (init_etx_sample_count == 0) { + return false; + } + if (!etx_info.etx_cache_storage_list) { //allocate etx_info.etx_cache_storage_list = ns_dyn_mem_alloc(sizeof(etx_sample_storage_t) * etx_info.ext_storage_list_size); @@ -622,6 +649,7 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_ etx_info.min_sample_count = etx_min_sample_count; etx_info.etx_min_sampling_time = min_wait_time; + etx_info.init_etx_sample_count = init_etx_sample_count; return true; } @@ -629,12 +657,23 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_ void etx_max_update_set(uint16_t etx_max_update) { if (etx_max_update) { + //Define MAX ETX UPDATE etx_info.max_etx_update = (etx_max_update / 128) << (12 - ETX_MOVING_AVERAGE_FRACTION); } else { etx_info.max_etx_update = 0; } } +void etx_max_set(uint16_t etx_max) +{ + if (etx_max) { + //Define MAX ETX possible value + etx_info.max_etx = (etx_max / 128) << 12; + } else { + etx_info.max_etx = 0xffff; + } +} + etx_storage_t *etx_storage_entry_get(int8_t interface_id, uint8_t attribute_index) { if (etx_info.interface_id != interface_id || !etx_info.etx_storage_list || attribute_index >= etx_info.ext_storage_list_size) { @@ -703,6 +742,8 @@ static void etx_value_change_callback_needed_check(uint16_t etx, uint16_t *store if (current_etx > *stored_diff_etx) { if (current_etx - *stored_diff_etx >= etx_info.hysteresis) { callback = true; + } else if (current_etx == etx_info.max_etx && *stored_diff_etx != etx_info.max_etx) { + callback = true; } } else if (current_etx < *stored_diff_etx) { if (*stored_diff_etx - current_etx >= etx_info.hysteresis) { diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index 55c125456d15..a820ee1b14ea 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -267,12 +267,13 @@ void etx_cache_timer(int8_t interface_id, uint16_t seconds_update); * * \param min_wait_time how many seconds must wait before do new ETX * \param etx_min_sample_count define how many completed TX process must be done for new ETX. Min accepted value is 4. + * \param init_etx_sample_count How Many sample is need to init etx calculate * * \return true Enable is OK * \return false Memory allocation fail * */ -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count); +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count); /** @@ -285,4 +286,14 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_ */ void etx_max_update_set(uint16_t etx_max_update); +/** + * \brief A function for set Maxium ETX value + * + * ETX RFC define that that Max value is 0xffff but this API cuold make that Poor link start go down slowly. + * + * \param etx_max 0 No limit for higher value means. This pameter will change normal ETX which could be 0xffff. + * + */ +void etx_max_set(uint16_t etx_max); + #endif /* ETX_H_ */ diff --git a/test/nanostack/unittest/stub/etx_stub.c b/test/nanostack/unittest/stub/etx_stub.c index eb2ef951618a..49f6a9743e60 100644 --- a/test/nanostack/unittest/stub/etx_stub.c +++ b/test/nanostack/unittest/stub/etx_stub.c @@ -87,7 +87,7 @@ void etx_cache_timer(int8_t interface_id, uint16_t seconds_update) } -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count) +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count) { return true; } diff --git a/test/nanostack/unittest/stub/ws_bootstrap_stub.c b/test/nanostack/unittest/stub/ws_bootstrap_stub.c index 1c5f1b55d69a..8263bfcdd95c 100644 --- a/test/nanostack/unittest/stub/ws_bootstrap_stub.c +++ b/test/nanostack/unittest/stub/ws_bootstrap_stub.c @@ -120,8 +120,3 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, { } - -void ws_bootstrap_etx_accelerate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh) -{ - -} diff --git a/test/nanostack/unittest/stub/ws_common_stub.c b/test/nanostack/unittest/stub/ws_common_stub.c index e704ef8ada6d..691dbe406081 100644 --- a/test/nanostack/unittest/stub/ws_common_stub.c +++ b/test/nanostack/unittest/stub/ws_common_stub.c @@ -83,8 +83,3 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con { return true; } - -void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh) -{ - -} From 73506346ca248d0a33e96c69806820113ab1d6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Wed, 20 Nov 2019 12:06:24 +0200 Subject: [PATCH 38/88] Corrected initial EAPOL-key trickle retries Minimum interval for first retry is now always at least 5 minutes and maximum can be 60 minutes on very slow network. Decreased number of retries from three to two to keep the time taken by the sequence roughly the same as before (previously sequence took about 15 to 20 minutes). After the last retry, the supplicant now waits for 2 to 4 minutes for authenticator to answer and not the expiry of last interval as before. For default network sizes, the I interval is from 6 to 12 minutes. There is also initial delay of 2 minutes before the first retry to ensure that the first retry happens at minimum at 5 minutes. This results that the first retry happens at 5 (2 + 3) to 14 (2 + 12) minutes after the initial attempt, and the second retry at 6 to 12 minutes from the first expiry of interval. The whole sequence (with 2 to 4 minutes wait after the last retry) takes on minimum 16 minutes and on maximum 30 minutes. On very slow networks, the I interval is from 10 to 60 minutes. This results that the first retry happens at 5 to 60 minutes after the initial attempt (there is no initial delay), and the second retry at 10 to 60 minutes from the first expiry of interval. The whole sequence (with 2 to 4 minutes wait after the last retry) takes on minimum 22 minutes and on maximum 124 minutes. --- source/6LoWPAN/ws/ws_pae_supp.c | 131 +++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 20 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 452f5993aef0..97c113bd677c 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -91,6 +91,7 @@ typedef struct { supp_entry_t entry; /**< Supplicant data */ kmp_addr_t target_addr; /**< EAPOL target (parent) address */ uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */ + uint16_t initial_key_retry_timer; /**< Timer to trigger initial EAPOL-Key 1st retry */ trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */ trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */ sec_prot_gtk_keys_t gtks; /**< GTKs */ @@ -98,6 +99,7 @@ typedef struct { sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */ timer_settings_t *timer_settings; /**< Timer settings */ uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */ + uint8_t initial_key_retry_cnt; /**< initial EAPOL-Key retry counter */ bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */ bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */ bool timer_running : 1; /**< Timer is running */ @@ -106,14 +108,30 @@ typedef struct { bool entry_address_active: 1; } pae_supp_t; +// How many times sending of initial EAPOL-key is retried +#define INITIAL_KEY_RETRY_COUNT 2 -#define TRICKLE_IMIN_180_SECS 180 +// How long the wait is before the first initial EAPOL-key retry +#define DEFAULT_INITIAL_KEY_RETRY_TIMER 120 +#define NONE_INITIAL_KEY_RETRY_TIMER 0 + +// Default trickle values for sending of initial EAPOL-key +#define DEFAULT_TRICKLE_IMIN_SECS 360 /* 6 to 12 minutes */ +#define DEFAULT_TRICKLE_IMAX_SECS 720 + +// Very slow network values for sending of initial EAPOL-key +#define VERY_SLOW_NW_TRICKLE_IMIN_SECS 600 /* 10 to 60 minutes */ +#define VERY_SLOW_NW_TRICKLE_IMAX_SECS 3600 + +// Trickle timer on how long to wait response after last retry before failing authentication +#define LAST_INTERVAL_TRICKLE_IMIN_SECS 240 /* 4 minutes */ +#define LAST_INTERVAL_TRICKLE_IMAX_SECS 240 static trickle_params_t initial_eapol_key_trickle_params = { - .Imin = TRICKLE_IMIN_180_SECS, /* 180 second; ticks are 1 second */ - .Imax = TRICKLE_IMIN_180_SECS << 1, /* 360 second */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 3 + .Imin = DEFAULT_TRICKLE_IMIN_SECS, /* 360 second; ticks are 1 second */ + .Imax = DEFAULT_TRICKLE_IMAX_SECS, /* 720 second */ + .k = 0, /* infinity - no consistency checking */ + .TimerExpirations = 2 }; static void ws_pae_supp_free(pae_supp_t *pae_supp); @@ -126,6 +144,8 @@ static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp); static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr); static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data); static void ws_pae_supp_tasklet_handler(arm_event_s *event); +static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp); +static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp); static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp); @@ -156,6 +176,7 @@ static const char *KEYS_FILE = KEYS_FILE_NAME; static int8_t tasklet_id = -1; static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link); +static uint8_t timing_value = 0; // Timing value set based e.g. on network size static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address) { @@ -323,14 +344,12 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt // Starts trickle trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); pae_supp->auth_trickle_running = true; + pae_supp->initial_key_retry_timer = 0; // Starts supplicant timer ws_pae_supp_timer_start(pae_supp); tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t); - } else { - // If trickle is already running, set inconsistent heard to speed up the trickle - trickle_inconsistent_heard(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); } } @@ -597,8 +616,10 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se pae_supp->nw_key_insert = NULL; pae_supp->nw_key_index_set = NULL; pae_supp->initial_key_timer = 0; + pae_supp->initial_key_retry_timer = 0; pae_supp->nw_keys_used_cnt = 0; pae_supp->timer_settings = timer_settings; + pae_supp->initial_key_retry_cnt = 0; pae_supp->auth_trickle_running = false; pae_supp->auth_requested = false; pae_supp->timer_running = false; @@ -702,6 +723,7 @@ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr) int8_t ws_pae_supp_timing_adjust(uint8_t timing) { + timing_value = timing; supp_fwh_sec_prot_timing_adjust(timing); supp_eap_sec_prot_timing_adjust(timing); return 0; @@ -817,14 +839,38 @@ void ws_pae_supp_slow_timer(uint16_t seconds) // Checks whether initial EAPOL-Key message needs to be re-send or new GTK request to be sent if (pae_supp->auth_trickle_running) { - if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) { - if (ws_pae_supp_initial_key_send(pae_supp) < 0) { - tr_info("EAPOL-Key send failed"); + if (pae_supp->initial_key_retry_timer > 0) { + if (pae_supp->initial_key_retry_timer > seconds) { + pae_supp->initial_key_retry_timer -= seconds; + } else { + pae_supp->initial_key_retry_timer = 0; + tr_info("initial key retry timer expired"); + } + } else { + // Checks if trickle timer expires + if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) { + if (pae_supp->initial_key_retry_cnt < INITIAL_KEY_RETRY_COUNT) { + if (ws_pae_supp_initial_key_send(pae_supp) < 0) { + tr_info("EAPOL-Key send failed"); + } + } + pae_supp->initial_key_retry_cnt++; + + /* Wait time for the authenticator to answer the last re-transmit expires; + fails authentication */ + if (pae_supp->initial_key_retry_cnt > INITIAL_KEY_RETRY_COUNT) { + ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); + } else if (pae_supp->initial_key_retry_cnt == INITIAL_KEY_RETRY_COUNT) { + // Starts wait time for the authenticator to answer + tr_info("Initial EAPOL-Key wait for last re-transmit answer"); + ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp); + } + } + + // Sanity check, should be running until authentication failure + if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) { + ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); } - } - // Maximum number of trickle expires, authentication fails - if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) { - ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); } } @@ -846,16 +892,61 @@ void ws_pae_supp_slow_timer(uint16_t seconds) if (ws_pae_supp_initial_key_send(pae_supp) < 0) { tr_info("EAPOL-Key send failed"); } - - // Starts trickle - pae_supp->auth_trickle_params = initial_eapol_key_trickle_params; - trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); - pae_supp->auth_trickle_running = true; + // Start trickle timer + ws_pae_supp_initial_trickle_timer_start(pae_supp); } } } } +static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp) +{ + pae_supp->auth_trickle_params = initial_eapol_key_trickle_params; + + // Very fast, medium and slow network + if (timing_value < 25) { + /* Starts trickle for initial EAPOL-key. Sequence has fixed delay of 2 minutes, + * one re-transmit interval, last re-transmit interval transmit time and a wait time + * for the authenticator to answer the last re-transmit. + * + * Interval I [6,12] minutes. Sequence: + * + * fixed 2 minutes delay + I + last I transmit time t + wait for answer [2,4] minutes + * + * There are two retries. Minimum time that sequence takes before authentication failure + * is 16 minutes and maximum is 30 minutes. + */ + pae_supp->initial_key_retry_timer = DEFAULT_INITIAL_KEY_RETRY_TIMER; // 2 minutes + } else { + /* Extremely slow network + * + * Starts trickle for initial EAPOL-key, Interval I [10,60] minutes. Sequence: + * I + last I transmit time t + wait for answer [2,4] minutes + * There are two retries. Minimum time that sequence takes before authentication failure + * is 22 minutes and maximum is 124 minutes. + */ + pae_supp->auth_trickle_params.Imin = VERY_SLOW_NW_TRICKLE_IMIN_SECS; + pae_supp->auth_trickle_params.Imax = VERY_SLOW_NW_TRICKLE_IMAX_SECS; + pae_supp->initial_key_retry_timer = NONE_INITIAL_KEY_RETRY_TIMER; // 0 seconds + } + trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); + tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); + pae_supp->auth_trickle_running = true; + pae_supp->initial_key_retry_cnt = 0; +} + +static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp) +{ + // Starts trickle last to wait response after last retry before failing authentication + pae_supp->auth_trickle_params = initial_eapol_key_trickle_params; + pae_supp->auth_trickle_params.Imin = LAST_INTERVAL_TRICKLE_IMIN_SECS; + pae_supp->auth_trickle_params.Imax = LAST_INTERVAL_TRICKLE_IMAX_SECS; + pae_supp->auth_trickle_params.TimerExpirations = 1; + // Set I to [iMin,iMax] (4 to 4 minutes) -> t is [I/2 - I] (2 minutes to 4 minutes) + trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); + tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); +} + static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp) { pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service); From d8dd18d89b65cb9e434120f8bc42032d72ea99b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Wed, 8 Jan 2020 05:38:53 +0200 Subject: [PATCH 39/88] Added ignoring of incoming security messages and improved EAP-TLS startup If supplicant authentication is not ongoing (during bootstrap or re-authentication), supplicant now ignores incoming security protocol messages. This results that e.g. if initial EAPOL-key message results mac TX failure, but authenticator has received the message (ack is lost), and authenticator starts EAP-TLS after the supplicant has returned to discover state, supplicant does not start EAP-TLS negotiation. Improved authenticator functionality on EAP-TLS identity request state. If supplicant has not received or has ignored the EAP-TLS identity request (e.g. because of mac TX failure) and authenticator receives initial EAPOL-key message from supplicant, authenticator now re-sends the the EAP-TLS identity request right away. --- source/6LoWPAN/ws/ws_pae_lib.c | 14 +++++++ source/6LoWPAN/ws/ws_pae_lib.h | 19 +++++++++ source/6LoWPAN/ws/ws_pae_supp.c | 25 ++++++++++-- .../eap_tls_sec_prot/auth_eap_tls_sec_prot.c | 39 ++++++++++++++++++- 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index 22d95b8086de..455ba76f64b2 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -291,6 +291,20 @@ void ws_pae_lib_supp_timer_ticks_set(supp_entry_t *entry, uint32_t ticks) entry->ticks = ticks; } +void ws_pae_lib_supp_timer_ticks_add(supp_entry_t *entry, uint32_t ticks) +{ + entry->ticks += ticks; +} + +bool ws_pae_lib_supp_timer_is_running(supp_entry_t *entry) +{ + if (entry->ticks == 0) { + return false; + } + + return true; +} + void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry) { if (entry->active) { diff --git a/source/6LoWPAN/ws/ws_pae_lib.h b/source/6LoWPAN/ws/ws_pae_lib.h index 90ba14812668..3ee6f10d0f3b 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.h +++ b/source/6LoWPAN/ws/ws_pae_lib.h @@ -272,6 +272,25 @@ void ws_pae_lib_supp_delete(supp_entry_t *entry); */ void ws_pae_lib_supp_timer_ticks_set(supp_entry_t *entry, uint32_t ticks); +/** + * ws_pae_lib_supp_timer_ticks_add adds supplicant timer ticks + * + * \param entry supplicant entry + * \param ticks ticks + * + */ +void ws_pae_lib_supp_timer_ticks_add(supp_entry_t *entry, uint32_t ticks); + +/** + * ws_pae_lib_supp_timer_is_running checks whether supplicant timer is running + * + * \param entry supplicant entry + * + * \return TRUE timer is running, FALSE timer is not running + * + */ +bool ws_pae_lib_supp_timer_is_running(supp_entry_t *entry); + /** * ws_pae_lib_supp_list_to_active move supplicant to active supplicants list * diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 97c113bd677c..d86a86690189 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -66,6 +66,9 @@ // Wait for re-authentication after GTK update #define WAIT_FOR_REAUTHENTICATION_TICKS 120 * 10 // 120 seconds +// Ticks added to wait for authenticator timer when authentication protocol is started (e.g. EAP-TLS) +#define START_AUTHENTICATION_TICKS 5 * 10 // 10 seconds + // How many times in maximum stored keys are used for authentication #define STORED_KEYS_MAXIMUM_USE_COUNT 1 @@ -146,6 +149,7 @@ static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data); static void ws_pae_supp_tasklet_handler(arm_event_s *event); static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp); static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp); +static bool ws_pae_supp_authentication_ongoing(pae_supp_t *pae_supp); static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp); @@ -823,7 +827,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks) bool running = ws_pae_lib_supp_timer_update(&pae_supp->entry, ticks, kmp_service_timer_if_timeout); // Checks whether timer needs to be active - if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) { + if (!ws_pae_supp_authentication_ongoing(pae_supp) && !running) { tr_debug("PAE idle"); // If not already completed, restart bootstrap ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); @@ -833,6 +837,17 @@ void ws_pae_supp_fast_timer(uint16_t ticks) } } +static bool ws_pae_supp_authentication_ongoing(pae_supp_t *pae_supp) +{ + /* When either bootstrap initial authentication or re-authentication is ongoing */ + if (pae_supp->initial_key_timer || pae_supp->auth_trickle_running || + ws_pae_lib_supp_timer_is_running(&pae_supp->entry)) { + return true; + } + + return false; +} + void ws_pae_supp_slow_timer(uint16_t seconds) { ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) { @@ -1105,7 +1120,9 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_ return NULL; } - if (!pae_supp->entry_address_active) { + // If target address is not set or authentication is not ongoing + if (!pae_supp->entry_address_active || !ws_pae_supp_authentication_ongoing(pae_supp)) { + tr_info("Incoming KMP rejected, auth not ongoing, type: %i ", type); // Does no longer wait for authentication, ignores message return NULL; } @@ -1131,6 +1148,9 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_ // Create new instance kmp = ws_pae_supp_kmp_create_and_start(service, type, pae_supp); + // Adds ticks to wait for authenticator to continue timer + ws_pae_lib_supp_timer_ticks_add(&pae_supp->entry, START_AUTHENTICATION_TICKS); + // For EAP-TLS create also TLS in addition to EAP-TLS if (type == IEEE_802_1X_MKA) { if (ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, TLS_PROT) != NULL) { @@ -1239,7 +1259,6 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8)); ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK); } - } static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp) diff --git a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c index 40a5c2eccdac..bc61ab1ac602 100644 --- a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c @@ -53,16 +53,24 @@ typedef enum { EAP_TLS_STATE_FINISHED = SEC_STATE_FINISHED } eap_tls_sec_prot_state_e; +// Filters initial EAPOL-key re-transmission bursts +#define BURST_FILTER_TIMER_TIMEOUT 5 * 10 + +// How many times initial EAPOL-key is accepted on wait for identity response state +#define INITIAL_EAPOL_KEY_MAX_COUNT 2 + typedef struct { sec_prot_common_t common; /**< Common data */ sec_prot_t *tls_prot; /**< TLS security protocol */ eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */ tls_data_t tls_send; /**< EAP-TLS send buffer */ tls_data_t tls_recv; /**< EAP-TLS receive buffer */ + uint16_t burst_filt_timer; /**< Burst filter timer */ uint8_t eap_id_seq; /**< EAP sequence */ uint8_t recv_eap_id_seq; /**< Last received EAP sequence */ uint8_t eap_code; /**< Received EAP code */ uint8_t eap_type; /**< Received EAP type */ + uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */ int8_t tls_result; /**< Result of TLS operation */ bool wait_tls: 1; /**< Wait TLS (ECC calculation) before sending EAP-TLS message */ bool tls_ongoing: 1; /**< TLS handshake is ongoing */ @@ -151,13 +159,15 @@ static int8_t auth_eap_tls_sec_prot_init(sec_prot_t *prot) sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_INIT); data->tls_prot = NULL; + data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT; data->eap_id_seq = 0; data->recv_eap_id_seq = 0; data->eap_code = 0; data->eap_type = 0; eap_tls_sec_prot_lib_message_init(&data->tls_recv); eap_tls_sec_prot_lib_message_init(&data->tls_send); - data->tls_result = EAP_TLS_RESULT_ERROR; + data->tls_result = EAP_TLS_RESULT_ERROR; + data->init_key_cnt = 0; data->wait_tls = false; data->tls_ongoing = false; data->send_pending = false; @@ -186,13 +196,31 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_ // Decoding is successful if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) { - // Handle only EAP messages (ignore initial EAPOL-key retransmissions) + // Handle EAP messages if (data->recv_eapol_pdu.packet_type == EAPOL_EAP_TYPE) { data->eap_code = data->recv_eapol_pdu.msg.eap.eap_code; data->eap_type = data->recv_eapol_pdu.msg.eap.type; // Call state machine prot->state_machine(prot); + } else if (data->recv_eapol_pdu.packet_type == EAPOL_KEY_TYPE && + sec_prot_state_get(&data->common) == EAP_TLS_STATE_RESPONSE_ID) { + /* If initial EAPOL-key transmission arrives to first EAP-TLS wait state i.e. + * when waiting for identity response, triggers re-transmission of identity + * request. This allows the supplicant to start EAP-TLS right away, if it has + * missed the original identity request. + */ + if (data->burst_filt_timer == 0 && data->init_key_cnt < INITIAL_EAPOL_KEY_MAX_COUNT) { + tr_info("EAP-TLS: initial EAPOL-key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + sec_prot_result_set(&data->common, SEC_RESULT_TIMEOUT); + // Call state machine + prot->state_machine(prot); + // Resets trickle timer to give time for supplicant to answer + sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + data->init_key_cnt++; + } + // Filters repeated initial EAPOL-key messages + data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT; } ret_val = 0; } @@ -288,6 +316,13 @@ static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) { eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + + if (data->burst_filt_timer > ticks) { + data->burst_filt_timer -= ticks; + } else { + data->burst_filt_timer = 0; + } + sec_prot_timer_timeout_handle(prot, &data->common, &eap_tls_trickle_params, ticks); } From 20289f675ddfbade5450e420e9982b82b372c0de Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Fri, 10 Jan 2020 10:48:49 +0200 Subject: [PATCH 40/88] Added periodic RPL version number increase After restart increase version number in 1 hour interval about 16 times then drop the rate to once in 12 hours --- source/6LoWPAN/ws/ws_bbr_api.c | 45 +++++++++++++++---- source/6LoWPAN/ws/ws_bbr_api_internal.h | 4 +- source/6LoWPAN/ws/ws_common.c | 10 ++--- source/6LoWPAN/ws/ws_common.h | 3 +- source/6LoWPAN/ws/ws_config.h | 5 ++- source/RPL/rpl_control.c | 7 ++- source/RPL/rpl_control.h | 2 +- .../unittest/stub/rpl_control_stub.c | 4 +- 8 files changed, 58 insertions(+), 22 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 4dfe7bb14df8..69f6aa9f30a5 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -85,7 +85,27 @@ static rpl_dodag_conf_t rpl_conf = { .dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY }; -void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase) +static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version) +{ + // Set the next timeout value for version update + if (version < 128) { + //stable version for RPL so slow timer update is ok + cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME; + } else { + cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART; + } +} + +static void ws_bbr_rpl_version_increase(protocol_interface_info_entry_t *cur) +{ + if (!protocol_6lowpan_rpl_root_dodag) { + return; + } + ws_bbr_rpl_version_timer_start(cur, rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag)); +} + + +void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase) { if (imin == 0 || doubling == 0) { // use default values @@ -111,11 +131,11 @@ void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint1 if (protocol_6lowpan_rpl_root_dodag) { rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf); - rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag); + ws_bbr_rpl_version_increase(cur); } } -static void ws_bbr_rpl_root_start(uint8_t *dodag_id) +static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t *dodag_id) { tr_info("RPL root start"); rpl_data_init_root(); @@ -132,6 +152,10 @@ static void ws_bbr_rpl_root_start(uint8_t *dodag_id) } // RPL memory limits set larger for Border router rpl_control_set_memory_limits(64 * 1024, 0); + + // Initial version number for RPL start is 240 from RPL RFC + ws_bbr_rpl_version_timer_start(cur, 240); + } static void ws_bbr_rpl_root_stop(void) @@ -350,7 +374,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) if (!protocol_6lowpan_rpl_root_dodag) { // Generate DODAGID if (ws_bbr_static_dodagid_create(cur) == 0) { - ws_bbr_rpl_root_start(current_dodag_id); + ws_bbr_rpl_root_start(cur, current_dodag_id); } } @@ -465,7 +489,8 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) } memcpy(current_global_prefix, global_prefix, 8); - rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag); + ws_bbr_rpl_version_increase(cur); + nd_proxy_downstream_interface_register(cur->id, ws_border_router_proxy_validate, ws_border_router_proxy_state_update); } else if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) { /* @@ -526,7 +551,7 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds if (cur->ws_info->pan_version_timer > seconds) { cur->ws_info->pan_version_timer -= seconds; } else { - // Border router has timed out + // PAN version number update tr_debug("Border router version number update"); cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config); cur->ws_info->pan_information.pan_version++; @@ -537,9 +562,13 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds ws_common_network_size_configure(cur, cur->ws_info->pan_information.pan_size); } } - + if (cur->ws_info->rpl_version_timer > seconds) { + cur->ws_info->rpl_version_timer -= seconds; + } else { + // RPL version update needed + ws_bbr_rpl_version_increase(cur); + } } - } uint16_t test_pan_size_override = 0xffff; diff --git a/source/6LoWPAN/ws/ws_bbr_api_internal.h b/source/6LoWPAN/ws/ws_bbr_api_internal.h index 5da59eabcfba..b07565a96c2a 100644 --- a/source/6LoWPAN/ws/ws_bbr_api_internal.h +++ b/source/6LoWPAN/ws/ws_bbr_api_internal.h @@ -27,7 +27,7 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur); -void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase); +void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase); bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur); @@ -36,7 +36,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur); #define ws_bbr_seconds_timer( cur, seconds) #define ws_bbr_pan_size(cur) 0 -#define ws_bbr_rpl_config( imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase) +#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase) #define ws_bbr_ready_to_start(cur) true #endif //HAVE_WS_BORDER_ROUTER diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 79a24317e277..bfefb4b04c80 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -338,11 +338,11 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint // doublings:3 (128s) // redundancy; 0 Disabled if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) { - ws_bbr_rpl_config(14, 3, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); + ws_bbr_rpl_config(cur, 14, 3, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); } else if (cur->ws_info->network_size_config == NETWORK_SIZE_CERTIFICATE) { - ws_bbr_rpl_config(0, 0, 0, WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE, WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE); + ws_bbr_rpl_config(cur, 0, 0, 0, WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE, WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE); } else { - ws_bbr_rpl_config(0, 0, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); + ws_bbr_rpl_config(cur, 0, 0, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); } ws_pae_controller_timing_adjust(1); // Fast and reactive network } else if (network_size < 300) { @@ -352,7 +352,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint // imin: 15 (32s) // doublings:5 (960s) // redundancy; 10 - ws_bbr_rpl_config(15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); + ws_bbr_rpl_config(cur, 15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); ws_pae_controller_timing_adjust(9); // medium limited network } else { // Configure the Wi-SUN discovery trickle parameters @@ -361,7 +361,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint // imin: 19 (524s, 9 min) // doublings:1 (1048s, 17 min) // redundancy; 10 May need some tuning still - ws_bbr_rpl_config(19, 1, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); + ws_bbr_rpl_config(cur, 19, 1, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); ws_pae_controller_timing_adjust(24); // Very slow and high latency network } return; diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 5e00e4c322ab..c5198cb4e138 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -88,7 +88,8 @@ typedef struct ws_info_s { parent_info_t parent_info[WS_PARENT_LIST_SIZE]; parent_info_list_t parent_list_free; parent_info_list_t parent_list_reserved; - uint32_t pan_version_timer; /**< border router version udate timeout */ + uint16_t rpl_version_timer; /**< RPL version update timeout */ + uint32_t pan_version_timer; /**< border router version update timeout */ uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ uint32_t pan_config_sol_max_timeout; uint8_t gtkhash[32]; diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 9ff0007021bd..85ed1bbf752e 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -46,7 +46,10 @@ #define PAN_VERSION_MEDIUM_NETWORK_LIFETIME 15*60 #define PAN_VERSION_LARGE_NETWORK_LIFETIME 30*60 //30min -#define RPL_VERSION_LIFETIME 5*3600 +// RPL version number update intervall +// after restart version numbers are increased faster and then slowed down when network is stable +#define RPL_VERSION_LIFETIME 12*3600 +#define RPL_VERSION_LIFETIME_RESTART 3600 /* Border router connection lost timeout * diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index fb287496adc4..5a05b010f71f 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -621,13 +621,16 @@ void rpl_control_increment_dtsn(rpl_dodag_t *dodag) //rpl_dodag_inconsistency(dodag); currently implied by rpl_dodag_increment_dtsn } -void rpl_control_increment_dodag_version(rpl_dodag_t *dodag) +uint8_t rpl_control_increment_dodag_version(rpl_dodag_t *dodag) { + uint8_t new_version = 240; if (rpl_dodag_am_root(dodag)) { - uint8_t new_version = rpl_seq_inc(rpl_dodag_get_version_number_as_root(dodag)); + new_version = rpl_seq_inc(rpl_dodag_get_version_number_as_root(dodag)); rpl_dodag_set_version_number_as_root(dodag, new_version); } + return new_version; } + void rpl_control_update_dodag_config(struct rpl_dodag *dodag, const rpl_dodag_conf_t *conf) { diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 013799e96514..d3d1011fe109 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -130,7 +130,7 @@ struct rpl_dodag *rpl_control_create_dodag_root(rpl_domain_t *domain, uint8_t in void rpl_control_delete_dodag_root(rpl_domain_t *domain, struct rpl_dodag *dodag); void rpl_control_update_dodag_route(struct rpl_dodag *dodag, const uint8_t *prefix, uint8_t prefix_len, uint8_t flags, uint32_t lifetime, bool age); void rpl_control_update_dodag_prefix(struct rpl_dodag *dodag, const uint8_t *prefix, uint8_t prefix_len, uint8_t flags, uint32_t lifetime, uint32_t preftime, bool age); -void rpl_control_increment_dodag_version(struct rpl_dodag *dodag); +uint8_t rpl_control_increment_dodag_version(struct rpl_dodag *dodag); void rpl_control_update_dodag_config(struct rpl_dodag *dodag, const rpl_dodag_conf_t *conf); void rpl_control_set_dodag_pref(struct rpl_dodag *dodag, uint8_t pref); void rpl_control_increment_dtsn(struct rpl_dodag *dodag); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index 70271fe12335..2cef3653abb4 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -144,9 +144,9 @@ void rpl_control_increment_dtsn(rpl_dodag_t *dodag) } -void rpl_control_increment_dodag_version(rpl_dodag_t *dodag) +uint8_t rpl_control_increment_dodag_version(rpl_dodag_t *dodag) { - + return 0; } void rpl_control_set_dodag_pref(rpl_dodag_t *dodag, uint8_t pref) From 588f202a51f2c464ac984b4488929200bf360110 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 9 Jan 2020 14:57:52 +0200 Subject: [PATCH 41/88] Wi-Sun RPL bootstrap update Small network and certicate network setup skip "Passive DIO scan phase" Specs say that Multicast DIS can be sended when we know that we have limiteted number of neighbours. Change-Id: I4be065f6ca00207b192093548bb3de9160f8ab3f --- source/6LoWPAN/ws/ws_bootstrap.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 3474f0aecb43..f55a0fbd9520 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2454,8 +2454,11 @@ static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) tr_debug("Start RPL learn"); // routers wait until RPL root is contacted ws_bootstrap_state_change(cur, ER_RPL_SCAN); - // Set timeout for check to 30 -60 seconds - cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT); + //For Large network and medium shuold do passive scan + if (cur->ws_info->network_size_config == NETWORK_SIZE_LARGE || cur->ws_info->network_size_config == NETWORK_SIZE_MEDIUM) { + // Set timeout for check to 30 -60 seconds + cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT); + } } /* From 71441212ea5316d376c3e7f8e5ecfb5a79e6a5e6 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 9 Jan 2020 15:14:48 +0200 Subject: [PATCH 42/88] RPL DIO Multicast message update Multicast DIO will include allways if rpl_control_set_dio_multicast_min_config_advertisment_count() set 0xff. Wi-sun Bootstrap set infinite advertisment rule for config advertisment. Change-Id: Iec2f52b33283729b675e4842b243c9acdd170653 --- source/6LoWPAN/ws/ws_config.h | 2 +- source/RPL/rpl_structures.h | 2 +- source/RPL/rpl_upward.c | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 85ed1bbf752e..468691d359a8 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -148,7 +148,7 @@ extern uint8_t DEVICE_MIN_SENS; */ #define WS_MAX_DAO_RETRIES 3 // With 40s, 80s, 160s, 320s, 640s #define WS_MAX_DAO_INITIAL_TIMEOUT 400 // With 40s initial value exponentially increasing -#define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 10 // Define 10 multicast advertisment when learn config or learn config update +#define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 0xff // Advertisment config at every MC DIO /* * Candidate parent list parameters diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 71c286f274e0..aadbc60c28e5 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -87,7 +87,7 @@ struct rpl_dodag { bool leaf: 1; /* We are a leaf in this DODAG (by policy) */ bool have_config: 1; /* We have the config */ bool used: 1; /* We have ever been a member of this DODAG? */ - uint8_t new_config_advertisment_count; /* We have advertiment new config at multicasti DIO */ + uint8_t new_config_advertisment_count; /* We have advertiment new config at multicasti DIO max updated value is 0xfe*/ NS_LIST_HEAD(rpl_dodag_version_t, link) versions; /* List of DODAG versions (newest first) */ prefix_list_t prefixes; /* Prefixes advertised in DIO PIOs */ rpl_dio_route_list_t routes; /* Routes advertised in DIO RIOs*/ diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index a50b6dc64ae5..d36df73d17c7 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1610,7 +1610,9 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_ conf = &dodag->config; } else if (dodag->new_config_advertisment_count < rpl_policy_dio_multicast_config_advertisment_min_count()) { conf = &dodag->config; - dodag->new_config_advertisment_count++; + if (dodag->new_config_advertisment_count < 0xfe) { + dodag->new_config_advertisment_count++; + } } else { conf = NULL; } From e3e5a00c555d34c16ac0a48c1b19f3ffe86cf3d4 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Fri, 10 Jan 2020 09:26:33 +0200 Subject: [PATCH 43/88] Timed parent selection timer trigger update Changed Trigged timed parent selection from delay multiple 0.9-1.1 --> 1.0-1.2. This will guarantee that we will allways wait iMin time to learn other candidate hear. Change-Id: I4c6c16ba5d3c1d9868f35d583c30bffaf6b7b775 --- source/RPL/rpl_upward.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index d36df73d17c7..4a41b84ed1d5 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -355,7 +355,7 @@ void rpl_instance_force_leaf(rpl_instance_t *instance) void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay) { if (instance->parent_selection_timer == 0 || instance->parent_selection_timer > delay) { - instance->parent_selection_timer = randLIB_randomise_base(delay, 0x7333, 0x8CCD) /* +/- 10% */; + instance->parent_selection_timer = randLIB_randomise_base(delay, 0x8000, 0x999A) /* Random between delay * 1.0-1.2 */; tr_debug("Timed parent triggered %u", instance->parent_selection_timer); } } From 7606ee87a9a504e294bbc0a17da9360a3be1ce54 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 14 Jan 2020 09:31:03 +0200 Subject: [PATCH 44/88] Wi-sun NS Aro registration blacklisting update When NS ARO message send fail we must blacklist device also similar way than at receive NA ARO cache full message. Change-Id: Ib5ad63e7ac6f0c145097df05c01632377ca35055 --- source/6LoWPAN/ws/ws_common.c | 6 ++---- source/6LoWPAN/ws/ws_common.h | 4 ++-- source/Common_Protocols/icmpv6.c | 4 ++-- test/nanostack/unittest/stub/ws_common_stub.c | 3 +-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index bfefb4b04c80..74a8dd18eed0 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -390,12 +390,10 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8 } } -void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full) +void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) { tr_warn("ARO registration Failure %s", trace_ipv6(ll_address)); - if (cache_full) { - blacklist_update(ll_address, false); - } + blacklist_update(ll_address, false); ws_bootstrap_aro_failure(cur, ll_address); } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index c5198cb4e138..aa977417ddd1 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -137,7 +137,7 @@ void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); -void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full); +void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); @@ -155,7 +155,7 @@ uint32_t ws_common_version_timeout_get(uint8_t config); #define ws_info(cur) ((ws_info_t *) NULL) #define ws_common_seconds_timer(cur, seconds) #define ws_common_neighbor_update(cur, ll_address) ((void) 0) -#define ws_common_aro_failure(cur, ll_address, cache_full) +#define ws_common_aro_failure(cur, ll_address) #define ws_common_neighbor_remove(cur, ll_address) #define ws_common_fast_timer(cur, ticks) ((void) 0) #define ws_common_allow_child_registration(cur, eui64) (false) diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 1a0f2c3355d5..32bcd71e1033 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -356,7 +356,7 @@ static void icmpv6_na_wisun_aro_handler(protocol_interface_info_entry_t *cur_int (void)life_time; if (nd_status != ARO_SUCCESS) { - ws_common_aro_failure(cur_interface, src_addr, true); + ws_common_aro_failure(cur_interface, src_addr); } } @@ -1389,7 +1389,7 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status) } rpl_control_address_register_done(buf->interface, ll_address, status); if (status != SOCKET_TX_DONE) { - ws_common_aro_failure(buf->interface, ll_address, false); + ws_common_aro_failure(buf->interface, ll_address); } } diff --git a/test/nanostack/unittest/stub/ws_common_stub.c b/test/nanostack/unittest/stub/ws_common_stub.c index 691dbe406081..2e145f2bc98d 100644 --- a/test/nanostack/unittest/stub/ws_common_stub.c +++ b/test/nanostack/unittest/stub/ws_common_stub.c @@ -67,11 +67,10 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa (void) interface; return true; } -void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full) +void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) { (void) cur; (void) ll_address; - (void) cache_full; } void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) { From 5cd094cd1d201e973978c8baecdb387df999a5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Mon, 13 Jan 2020 15:01:52 +0200 Subject: [PATCH 45/88] Corrected GTK update initial EAPOL-key trickle timer Trickle timer on GTK update works now correctly. Initial EAPOL-key is send on maximum three times to authenticator when GTK hash mismatch is detected. --- source/6LoWPAN/ws/ws_pae_supp.c | 50 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index d86a86690189..bde4539ce2f4 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -149,6 +149,7 @@ static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data); static void ws_pae_supp_tasklet_handler(arm_event_s *event); static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp); static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp); +static void ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp_t *pae_supp, uint8_t timer_expirations); static bool ws_pae_supp_authentication_ongoing(pae_supp_t *pae_supp); static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp); @@ -339,16 +340,8 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt if (mismatch == GTK_LIFETIME_MISMATCH) { timer_expirations = 1; } - - pae_supp->auth_trickle_params.Imin = pae_supp->timer_settings->gtk_request_imin; - pae_supp->auth_trickle_params.Imax = pae_supp->timer_settings->gtk_request_imax; - pae_supp->auth_trickle_params.k = 0; - pae_supp->auth_trickle_params.TimerExpirations = timer_expirations; - - // Starts trickle - trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); - pae_supp->auth_trickle_running = true; - pae_supp->initial_key_retry_timer = 0; + // Start trickle timer + ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, timer_expirations); // Starts supplicant timer ws_pae_supp_timer_start(pae_supp); @@ -623,7 +616,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se pae_supp->initial_key_retry_timer = 0; pae_supp->nw_keys_used_cnt = 0; pae_supp->timer_settings = timer_settings; - pae_supp->initial_key_retry_cnt = 0; + pae_supp->initial_key_retry_cnt = INITIAL_KEY_RETRY_COUNT; pae_supp->auth_trickle_running = false; pae_supp->auth_requested = false; pae_supp->timer_running = false; @@ -864,21 +857,25 @@ void ws_pae_supp_slow_timer(uint16_t seconds) } else { // Checks if trickle timer expires if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) { - if (pae_supp->initial_key_retry_cnt < INITIAL_KEY_RETRY_COUNT) { + if (pae_supp->initial_key_retry_cnt > 0) { if (ws_pae_supp_initial_key_send(pae_supp) < 0) { tr_info("EAPOL-Key send failed"); } } - pae_supp->initial_key_retry_cnt++; /* Wait time for the authenticator to answer the last re-transmit expires; fails authentication */ - if (pae_supp->initial_key_retry_cnt > INITIAL_KEY_RETRY_COUNT) { + if (pae_supp->initial_key_retry_cnt == 0) { ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); - } else if (pae_supp->initial_key_retry_cnt == INITIAL_KEY_RETRY_COUNT) { - // Starts wait time for the authenticator to answer - tr_info("Initial EAPOL-Key wait for last re-transmit answer"); - ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp); + } else { + if (pae_supp->initial_key_retry_cnt > 0) { + pae_supp->initial_key_retry_cnt--; + } + if (pae_supp->initial_key_retry_cnt == 0) { + // Starts wait time for the authenticator to answer + tr_info("Initial EAPOL-Key wait for last re-transmit answer"); + ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp); + } } } @@ -947,7 +944,7 @@ static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp) trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); pae_supp->auth_trickle_running = true; - pae_supp->initial_key_retry_cnt = 0; + pae_supp->initial_key_retry_cnt = INITIAL_KEY_RETRY_COUNT; } static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp) @@ -962,6 +959,21 @@ static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pa tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); } +static void ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp_t *pae_supp, uint8_t timer_expirations) +{ + // Starts trickle for the key update + pae_supp->auth_trickle_params.Imin = pae_supp->timer_settings->gtk_request_imin; + pae_supp->auth_trickle_params.Imax = pae_supp->timer_settings->gtk_request_imax; + pae_supp->auth_trickle_params.k = 0; + pae_supp->auth_trickle_params.TimerExpirations = timer_expirations; + + trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); + tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t); + pae_supp->initial_key_retry_timer = NONE_INITIAL_KEY_RETRY_TIMER; // 0 seconds + pae_supp->auth_trickle_running = true; + pae_supp->initial_key_retry_cnt = timer_expirations; +} + static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp) { pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service); From 99e6efac6c5ffab644ea9d28462bc3782ead9e6b Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 14 Jan 2020 13:52:45 +0200 Subject: [PATCH 46/88] Neighbour remove operation update Now neighbour remove clean Normal and Indrect TX queue's. Change-Id: I58c4a48a5ff099c6bba3b22530601eee72884e1e --- .../Generic/protocol_6lowpan_bootstrap.c | 2 +- source/6LoWPAN/Thread/thread_bootstrap.c | 2 +- source/6LoWPAN/adaptation_interface.c | 17 +++++++++++++---- source/6LoWPAN/lowpan_adaptation_interface.h | 4 ++-- source/6LoWPAN/ws/ws_bootstrap.c | 2 +- .../test_adaptation_interface.c | 14 +++++++------- .../unittest/stub/adaptation_interface_stub.c | 2 +- 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index 005e8d84e9e0..cbe3e12c67e2 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1595,7 +1595,7 @@ static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entr { protocol_interface_info_entry_t *cur_interface = user_data; - lowpan_adaptation_remove_free_indirect_table(cur_interface, entry_ptr); + lowpan_adaptation_neigh_remove_free_tx_tables(cur_interface, entry_ptr); // Sleepy host if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { mac_data_poll_protocol_poll_mode_decrement(cur_interface); diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 84d0609fb28d..483932b57818 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -137,7 +137,7 @@ static void thread_bootstrap_pbbr_update_done(struct protocol_interface_info_ent static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { protocol_interface_info_entry_t *cur = user_data; - lowpan_adaptation_remove_free_indirect_table(cur, entry_ptr); + lowpan_adaptation_neigh_remove_free_tx_tables(cur, entry_ptr); thread_reset_neighbour_info(cur, entry_ptr); //Removes ETX neighbor diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index c4fd8fe536fd..a4bc2ebea7bf 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -1446,19 +1446,19 @@ static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interf return true; } -void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) +void lowpan_adaptation_neigh_remove_free_tx_tables(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) { //Free first by defined short address if (entry_ptr->mac16 < 0xfffe) { uint8_t temp_address[2]; common_write_16_bit(entry_ptr->mac16, temp_address); - lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, temp_address, ADDR_802_15_4_SHORT); + lowpan_adaptation_free_messages_from_queues_by_address(cur_interface, temp_address, ADDR_802_15_4_SHORT); } - lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, entry_ptr->mac64, ADDR_802_15_4_LONG); + lowpan_adaptation_free_messages_from_queues_by_address(cur_interface, entry_ptr->mac64, ADDR_802_15_4_LONG); } -int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type) +int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type) { fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); @@ -1474,9 +1474,18 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr } } + //Check next direct queue + ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->activeUnicastList) { + if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { + //Purge from mac + lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); + } + } + return 0; } + int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child) { fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); diff --git a/source/6LoWPAN/lowpan_adaptation_interface.h b/source/6LoWPAN/lowpan_adaptation_interface.h index 562e4820340e..307dd9917be4 100644 --- a/source/6LoWPAN/lowpan_adaptation_interface.h +++ b/source/6LoWPAN/lowpan_adaptation_interface.h @@ -51,9 +51,9 @@ struct buffer *lowpan_adaptation_reassembly(struct protocol_interface_info_entry bool lowpan_adaptation_tx_active(int8_t interface_id); -void lowpan_adaptation_remove_free_indirect_table(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *entry_ptr); +void lowpan_adaptation_neigh_remove_free_tx_tables(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *entry_ptr); -int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type); +int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type); int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child); diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index f55a0fbd9520..ed7cee4a9e07 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -1570,7 +1570,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt { protocol_interface_info_entry_t *cur = user_data; - lowpan_adaptation_remove_free_indirect_table(cur, entry_ptr); + lowpan_adaptation_neigh_remove_free_tx_tables(cur, entry_ptr); // Sleepy host if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { mac_data_poll_protocol_poll_mode_decrement(cur); diff --git a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c index 0887389d0806..a847218f8387 100644 --- a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c +++ b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c @@ -320,21 +320,21 @@ bool test_lowpan_adaptation_indirect_purge() } entry.id = 2; if (-1 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf->dst_sa.address, test_buf->dst_sa.addr_type)) { return false; } entry.id = 0; if (-0 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf->dst_sa.address, test_buf->dst_sa.addr_type)) { return false; } if (-0 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf2->dst_sa.address, ADDR_NONE)) { return false; } @@ -342,7 +342,7 @@ bool test_lowpan_adaptation_indirect_purge() // purge with addr none test_buf2->dst_sa.addr_type = ADDR_NONE; if (-0 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf2->dst_sa.address, ADDR_NONE)) { return false; } @@ -351,7 +351,7 @@ bool test_lowpan_adaptation_indirect_purge() test_buf2->dst_sa.address[2] = 2; if (-0 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf2->dst_sa.address, test_buf2->dst_sa.addr_type)) { return false; @@ -360,7 +360,7 @@ bool test_lowpan_adaptation_indirect_purge() test_buf2->dst_sa.address[2] = 0; if (-0 - != lowpan_adaptation_indirect_free_messages_from_queues_by_address( + != lowpan_adaptation_free_messages_from_queues_by_address( &entry, test_buf2->dst_sa.address, test_buf2->dst_sa.addr_type)) { return false; @@ -1371,7 +1371,7 @@ bool test_lowpan_adaptation_interface_mpx_register() lowpan_adaptation_interface_tx(&entry, test_buf2); - if (0 != lowpan_adaptation_indirect_free_messages_from_queues_by_address(&entry, test_buf2->dst_sa.address, + if (0 != lowpan_adaptation_free_messages_from_queues_by_address(&entry, test_buf2->dst_sa.address, test_buf2->dst_sa.addr_type)) { lowpan_adaptation_interface_free(0); free(test_buf); diff --git a/test/nanostack/unittest/stub/adaptation_interface_stub.c b/test/nanostack/unittest/stub/adaptation_interface_stub.c index 3091f529554e..c2536775ee52 100644 --- a/test/nanostack/unittest/stub/adaptation_interface_stub.c +++ b/test/nanostack/unittest/stub/adaptation_interface_stub.c @@ -98,7 +98,7 @@ void lowpan_adaptation_interface_etx_update_enable(int8_t interface_id) } -void lowpan_adaptation_remove_free_indirect_table(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *entry_ptr) +void lowpan_adaptation_neigh_remove_free_tx_tables(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *entry_ptr) { } From fd6ce049a36a0cafbaa0f22b615a3e5c89b145b6 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 14 Jan 2020 14:00:56 +0200 Subject: [PATCH 47/88] Thread Child ml16 update clear old address queue's and registered address. Change-Id: I7a735c941467de51997e7881d4f6c830fc7ac9b4 --- .../Thread/thread_mle_message_handler.c | 2 +- source/6LoWPAN/Thread/thread_network_synch.c | 19 +++++++++++++++++-- .../6LoWPAN/Thread/thread_router_bootstrap.c | 8 -------- .../test_adaptation_interface.c | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index a8253c5f8eb7..31e2f3416ca1 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -285,7 +285,7 @@ static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_me if (short_address != entry_temp->mac16) { if (thread_router_addr_from_addr(entry_temp->mac16) == cur->thread_info->routerShortAddress) { thread_dynamic_storage_child_info_clear(cur->id, entry_temp); - protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16); + } entry_temp->mac16 = short_address; /* throw MLME_GET request, short address is changed automatically in get request callback */ diff --git a/source/6LoWPAN/Thread/thread_network_synch.c b/source/6LoWPAN/Thread/thread_network_synch.c index 0ef70d38f18e..1ffbdc8da977 100644 --- a/source/6LoWPAN/Thread/thread_network_synch.c +++ b/source/6LoWPAN/Thread/thread_network_synch.c @@ -64,6 +64,7 @@ #include "Common_Protocols/icmpv6_radv.h" #include "MLE/mle.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" +#include "6LoWPAN/lowpan_adaptation_interface.h" #include "6LoWPAN/MAC/mac_helper.h" #define TRACE_GROUP "tsyn" @@ -192,15 +193,29 @@ void thread_dynamic_storage_child_info_store(protocol_interface_info_entry_t *cu void thread_dynamic_storage_child_info_clear(int8_t interface_id, struct mac_neighbor_table_entry *child) { + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return; + } thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(interface_id, child); + if (child_info) { // Clear child information memset(child_info, 0, sizeof(thread_sync_child_info_t)); tr_debug("Dynamic storage: cleared child; mac16=%04x", child->mac16); - return; } - return; + uint8_t temp_address[2]; + common_write_16_bit(child->mac16, temp_address); + //Release Old short address entries + lowpan_adaptation_free_messages_from_queues_by_address(cur, temp_address, ADDR_802_15_4_SHORT); + /* As we are losing a link to a child address, we can assume that if we have an IP neighbour cache + * mapping to that address, it is no longer valid. We must have been their parent, and they must be + * finding a new parent, and hence a new 16-bit address. (Losing a link to a router address would not + * invalidate our IP->16-bit mapping.) + */ + protocol_6lowpan_release_short_link_address_from_neighcache(cur, child->mac16); + } static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mac_neighbor_table_entry_t *child) diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 1f17c7e5696b..81d544944756 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -969,13 +969,6 @@ int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cu tr_debug("Child free %x", child->mac16); thread_dynamic_storage_child_info_clear(cur->id, child); - /* As we are losing a link to a child address, we can assume that if we have an IP neighbour cache - * mapping to that address, it is no longer valid. We must have been their parent, and they must be - * finding a new parent, and hence a new 16-bit address. (Losing a link to a router address would not - * invalidate our IP->16-bit mapping.) - */ - protocol_6lowpan_release_short_link_address_from_neighcache(cur, child->mac16); - // If Child's RLOC16 appears in the Network Data send the RLOC16 to the Leader if (thread_network_data_services_registered(&cur->thread_info->networkDataStorage, child->mac16)) { tr_debug("Remove references to Child's RLOC16 from the Network Data"); @@ -1824,7 +1817,6 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t * // Was this previously our child? If yes, update. if ((entry_temp->mac16 & THREAD_CHILD_MASK) && thread_router_addr_from_addr(entry_temp->mac16) == cur->thread_info->routerShortAddress) { thread_dynamic_storage_child_info_clear(cur->id, entry_temp); - protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16); } update_mac_mib = true; entry_temp->mac16 = shortAddress; // short address refreshed diff --git a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c index a847218f8387..41c91265b6fe 100644 --- a/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c +++ b/test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c @@ -1372,7 +1372,7 @@ bool test_lowpan_adaptation_interface_mpx_register() if (0 != lowpan_adaptation_free_messages_from_queues_by_address(&entry, test_buf2->dst_sa.address, - test_buf2->dst_sa.addr_type)) { + test_buf2->dst_sa.addr_type)) { lowpan_adaptation_interface_free(0); free(test_buf); free(test_buf2); From 807632dd94dc1f6259031d9dc5da2cae1a0ba6da Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Mon, 20 Jan 2020 10:12:15 +0200 Subject: [PATCH 48/88] DHCP server freed next free allocated id This fix a bug when 1 freed id is re-allocated and it set next free id to point already active ones. Change-Id: Ia3ab76f1800cbee41f8b82aea3fc7f455132c6dc --- source/libDHCPv6/libDHCPv6_server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index df8a72cb9141..f3c0ccba8c64 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -75,7 +75,8 @@ static uint16_t libdhcpv6_get_next_freed_id(dhcpv6_gua_server_entry_s *serverInf if ((cur->allocatedID - last_allocated_id) == 2) { //one missing sequence between last and current if (last_allocated_id + 1 == serverInfo->firstFreedId) { - //Skip + //Skip Current freedID this will update after this call to new one + last_allocated_id = cur->allocatedID; continue; } } else if (last_allocated_id + 1 == serverInfo->firstFreedId) { From d5cf8d52e21738f1f704aeff393ae8409b6348a8 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 22 Jan 2020 13:42:35 +0200 Subject: [PATCH 49/88] Clean ARMC6/GCC compiler warnings (#2278) Clean ARMC6/GCC compiler warnings from all nanostack configurations. --- source/6LoWPAN/MAC/mac_helper.c | 1 + source/6LoWPAN/MAC/mac_response_handler.c | 1 + source/6LoWPAN/ND/nd_router_object.c | 2 ++ source/6LoWPAN/Thread/thread_test_api.c | 3 +-- source/6LoWPAN/ws/ws_bbr_api.c | 4 ++-- source/6LoWPAN/ws/ws_pae_auth.h | 2 +- source/6LoWPAN/ws/ws_pae_nvm_data.c | 10 ++++++++-- source/Common_Protocols/icmpv6_radv.c | 3 +++ source/Common_Protocols/ipv6.c | 6 ++++++ source/Core/ns_socket.c | 8 ++++++-- source/MAC/IEEE802_15_4/mac_mlme.c | 1 + source/Security/TLS/tls_lib.c | 1 + .../protocols/key_sec_prot/key_sec_prot.c | 4 ++-- source/Service_Libs/fhss/fhss.c | 2 ++ source/libNET/src/net_6lowpan_parameter_api.c | 5 +++++ source/libNET/src/net_load_balance.c | 16 ++++++++++++++-- source/libNET/src/ns_net.c | 9 ++++++++- source/libNET/src/socket_api.c | 9 ++++++++- 18 files changed, 72 insertions(+), 15 deletions(-) diff --git a/source/6LoWPAN/MAC/mac_helper.c b/source/6LoWPAN/MAC/mac_helper.c index 1f7de87fc7da..e33c7fe6f958 100644 --- a/source/6LoWPAN/MAC/mac_helper.c +++ b/source/6LoWPAN/MAC/mac_helper.c @@ -887,6 +887,7 @@ int8_t mac_helper_key_link_frame_counter_set(int8_t interface_id, uint32_t seq_p void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index, uint8_t *mac64) { + (void) mac64; if (!mac_api) { return; } diff --git a/source/6LoWPAN/MAC/mac_response_handler.c b/source/6LoWPAN/MAC/mac_response_handler.c index 1c89a92578c5..87d3003bbc68 100644 --- a/source/6LoWPAN/MAC/mac_response_handler.c +++ b/source/6LoWPAN/MAC/mac_response_handler.c @@ -120,6 +120,7 @@ void mcps_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *d void mcps_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data) { (void)api; + (void)data; tr_info("MCPS Data Purge confirm status %u, for handle %u", data->status, data->msduHandle); } diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index 41a051816cc2..00beb5039f5d 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -1754,6 +1754,8 @@ void nd_6lowpan_set_radv_params(protocol_interface_info_entry_t *cur_interface) cur_interface->adv_retrans_timer = nd_params.ra_retrans_timer; cur_interface->max_initial_rtr_adv_interval = nd_params.ra_interval_min; cur_interface->max_initial_rtr_advertisements = nd_params.ra_transmits; +#else + (void) cur_interface; #endif } #endif // HAVE_6LOWPAN_ND diff --git a/source/6LoWPAN/Thread/thread_test_api.c b/source/6LoWPAN/Thread/thread_test_api.c index 26b7dd9250ab..bc137b1a9f02 100644 --- a/source/6LoWPAN/Thread/thread_test_api.c +++ b/source/6LoWPAN/Thread/thread_test_api.c @@ -643,11 +643,10 @@ int thread_test_version_set(int8_t interface_id, uint8_t version) int thread_test_pbbr_response_override_set(int8_t interface_id, uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count) { -#ifdef HAVE_THREAD +#if defined(HAVE_THREAD) && defined(HAVE_THREAD_V2) && defined(HAVE_THREAD_BORDER_ROUTER) (void)interface_id; thread_bbr_commercial_status_override_set(dua_status, dua_count, ba_failure_count); return 0; - #else (void)interface_id; (void)dua_status; diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 69f6aa9f30a5..d18d0c0ff507 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -45,10 +45,10 @@ #define RPL_INSTANCE_ID 1 -static uint8_t current_instance_id = RPL_INSTANCE_ID; - #ifdef HAVE_WS_BORDER_ROUTER +static uint8_t current_instance_id = RPL_INSTANCE_ID; + #define WS_ULA_LIFETIME 24*3600 #define WS_ROUTE_LIFETIME WS_ULA_LIFETIME #define WS_DHCP_ADDRESS_LIFETIME 2*3600 diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index 5c0f35d96091..04bd157d7892 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -232,7 +232,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #else #define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, timer_settings) 1 -#define ws_pae_auth_timing_adjust(timing) 1 +#define ws_pae_auth_timing_adjust(timing) #define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1 #define ws_pae_auth_delete NULL #define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set) {(void) hash_set;} diff --git a/source/6LoWPAN/ws/ws_pae_nvm_data.c b/source/6LoWPAN/ws/ws_pae_nvm_data.c index d7f2d23861ac..7f833430a619 100644 --- a/source/6LoWPAN/ws/ws_pae_nvm_data.c +++ b/source/6LoWPAN/ws/ws_pae_nvm_data.c @@ -57,7 +57,7 @@ nvm_tlv_entry_t *ws_pae_buffer_allocate(void) void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) { - + int len; tlv_entry->tag = PAE_NVM_NW_INFO_TAG; tlv_entry->len = PAE_NVM_NW_INFO_LEN; @@ -66,7 +66,13 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa tlv = common_write_16_bit(pan_id, tlv); memset(tlv, 0, 33); - strncpy((char *)tlv, nw_name, 32); + // use strnlen & memset instead of strncpy to avoid gcc warning: + // call to __builtin___strncpy_chk will always overflow destination buffer [-Werror] + len = strlen(nw_name); + if (len > 32) { + len = 32; + } + memcpy((char *)tlv, nw_name, len); tlv += 33; for (uint8_t i = 0; i < GTK_NUM; i++) { diff --git a/source/Common_Protocols/icmpv6_radv.c b/source/Common_Protocols/icmpv6_radv.c index fff4edec989b..446d05f38ec1 100644 --- a/source/Common_Protocols/icmpv6_radv.c +++ b/source/Common_Protocols/icmpv6_radv.c @@ -325,6 +325,9 @@ void icmpv6_stop_router_advertisements(protocol_interface_info_entry_t *cur, con */ static void icmpv6_send_ra(protocol_interface_info_entry_t *cur, const uint8_t *dest, const uint8_t *abro) { +#ifndef HAVE_RPL + (void) abro; +#endif if (cur->nwk_id == IF_6LoWPAN) { nd_ra_build_by_abro(abro, dest, cur); } else { diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index fe3102591d7c..11df4aafa45a 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -773,6 +773,9 @@ static buffer_t *ipv6_tunnel_exit(buffer_t *buf, uint8_t *payload) static buffer_t *ipv6_handle_options(buffer_t *buf, protocol_interface_info_entry_t *cur, uint8_t *ptr, uint8_t nh, uint16_t payload_length, uint16_t *hdrlen_out, const sockaddr_t *ll_src, bool pre_fragment) { (void) nh; +#ifndef HAVE_RPL + (void) ll_src; +#endif if (payload_length < 2) { return icmpv6_error(buf, cur, ICMPV6_TYPE_ERROR_PARAMETER_PROBLEM, ICMPV6_CODE_PARAM_PRB_HDR_ERR, 4); } @@ -853,6 +856,9 @@ static buffer_t *ipv6_handle_options(buffer_t *buf, protocol_interface_info_entr static buffer_t *ipv6_handle_routing_header(buffer_t *buf, protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t payload_length, uint16_t *hdrlen_out, bool *forward_out, bool pre_fragment) { +#ifndef HAVE_RPL + (void) forward_out; +#endif if (buf->options.ll_security_bypass_rx) { tr_warn("Routing header: Security check fail"); protocol_stats_update(STATS_IP_RX_DROP, 1); diff --git a/source/Core/ns_socket.c b/source/Core/ns_socket.c index 24f7738c6fab..05961ccb5b18 100644 --- a/source/Core/ns_socket.c +++ b/source/Core/ns_socket.c @@ -287,14 +287,16 @@ void socket_release(socket_t *socket) if (tcp_info(socket->inet_pcb)) { /* This may trigger a reset if pending data. Do it first so you * get just the reset, rather than a FIN. */ - tcp_session_shutdown_read(tcp_info(socket->inet_pcb)); + tcp_error sock_status = tcp_session_shutdown_read(tcp_info(socket->inet_pcb)); /* This can also cause TCP deletion */ if (tcp_info(socket->inet_pcb)) { - tcp_session_close(tcp_info(socket->inet_pcb)); + sock_status = tcp_session_close(tcp_info(socket->inet_pcb)); } if (tcp_info(socket->inet_pcb)) { tcp_socket_released(tcp_info(socket->inet_pcb)); } + // prevent warning "statement with no effect" when TCP is disabled + (void) sock_status; } else { /* Unbind the internet control block - ensures users are not prevented * from binding a new socket to the same port if the socket lingers @@ -1362,8 +1364,10 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr protocol_push(buf); +#ifndef NO_TCP /* TCP jumps back to here */ success: +#endif if (flags & NS_MSG_LEGACY0) { return 0; } else { diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index 5d1f5e48c925..478b8a9d88ee 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -783,6 +783,7 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) set_req->value_pointer); mac_mlme_set_symbol_rate(rf_mac_setup); phy_rf_channel_configuration_s *config_params = (phy_rf_channel_configuration_s *)set_req->value_pointer; + (void) config_params; // unused variable if traces disabled tr_info("RF config update:"); tr_info("Frequency(ch0): %"PRIu32"Hz", config_params->channel_0_center_frequency); tr_info("Channel spacing: %"PRIu32"Hz", config_params->channel_spacing); diff --git a/source/Security/TLS/tls_lib.c b/source/Security/TLS/tls_lib.c index b4596c9f4af7..f23517a62c0b 100644 --- a/source/Security/TLS/tls_lib.c +++ b/source/Security/TLS/tls_lib.c @@ -229,6 +229,7 @@ uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suit case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: thep->client_knows_standard_ecc_ciphersuite = true; /* no break */ + /* fall through */ case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_COMPAT: tr_debug("Client Sup ECC"); ret_val |= SEC_CIPHERSUITE_ECC; diff --git a/source/Security/protocols/key_sec_prot/key_sec_prot.c b/source/Security/protocols/key_sec_prot/key_sec_prot.c index ba56a7566c6b..409546c3dc21 100644 --- a/source/Security/protocols/key_sec_prot/key_sec_prot.c +++ b/source/Security/protocols/key_sec_prot/key_sec_prot.c @@ -318,10 +318,10 @@ static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e // Indicates TX failure if (tx_status == SEC_PROT_TX_ERR_TX_NO_ACK) { - sec_prot_result_set(&data->common, KMP_RESULT_ERR_TX_NO_ACK); + sec_prot_result_set(&data->common, SEC_RESULT_ERR_TX_NO_ACK); } else if (tx_status != SEC_PROT_TX_OK) { // Indicates other failure - sec_prot_result_set(&data->common, KMP_RESULT_ERR_UNSPEC); + sec_prot_result_set(&data->common, SEC_RESULT_ERR_UNSPEC); } prot->state_machine_call(prot); return 0; diff --git a/source/Service_Libs/fhss/fhss.c b/source/Service_Libs/fhss/fhss.c index 5bc05a1a29b6..ae960bc8d07c 100644 --- a/source/Service_Libs/fhss/fhss.c +++ b/source/Service_Libs/fhss/fhss.c @@ -1385,7 +1385,9 @@ static void fhss_beacon_tasklet_func(arm_event_s *event) if (!fhss_structure) { return; } +#ifdef FEA_TRACE_SUPPORT uint8_t parent_address[8]; +#endif fhss_clear_active_event(fhss_structure, event->event_type); // skip the init event as there will be a timer event after if (event->event_type == FHSS_TIMER_EVENT) { diff --git a/source/libNET/src/net_6lowpan_parameter_api.c b/source/libNET/src/net_6lowpan_parameter_api.c index 59bea2198aa4..cd1649df3c8f 100644 --- a/source/libNET/src/net_6lowpan_parameter_api.c +++ b/source/libNET/src/net_6lowpan_parameter_api.c @@ -65,6 +65,7 @@ int8_t net_6lowpan_nd_parameter_set(const nd_parameters_s *p) return 0; #else + (void) p; return -2; #endif } @@ -89,6 +90,8 @@ int8_t net_6lowpan_nd_timer_base_tick_set(uint8_t base_tick_x_100ms) } nd_base_tick = base_tick_x_100ms; +#else + (void) base_tick_x_100ms; #endif return 0; } @@ -103,5 +106,7 @@ void net_6lowpan_nd_parameter_read(nd_parameters_s *p) { #ifdef HAVE_6LOWPAN_ND *p = nd_params; +#else + (void) p; #endif } diff --git a/source/libNET/src/net_load_balance.c b/source/libNET/src/net_load_balance.c index 90f4960dffd2..a643d90fde3d 100644 --- a/source/libNET/src/net_load_balance.c +++ b/source/libNET/src/net_load_balance.c @@ -146,12 +146,14 @@ int8_t net_load_balance_network_switch_cb_set(int8_t interface_id, net_load_bala return load_balance_network_switch_cb_set(interface_ptr->lb_api, network_switch_notify); #else + (void) interface_id; + (void) network_switch_notify; return -1; #endif } -int8_t net_load_balance_create(int8_t interface_id, bool enable_periodic_beacon_interval) +int8_t net_load_balance_create(int8_t interface_id, bool enable_periodic_beacon_interval) { #ifdef HAVE_6LOWPAN_ND protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id); @@ -188,6 +190,8 @@ int8_t net_load_balance_create(int8_t interface_id, bool enable_periodic_beacon return 0; #else + (void) interface_id; + (void) enable_periodic_beacon_interval; return -1; #endif } @@ -205,6 +209,7 @@ int8_t net_load_balance_delete(int8_t interface_id) return load_balance_delete(lb_api); #else + (void) interface_id; return -1; #endif } @@ -223,6 +228,9 @@ int8_t net_load_balance_threshold_set(int8_t interface_id, uint8_t threshold_min return load_balance_network_threshold_set(interface_ptr->lb_api, threshold_min, threshold_max); #else + (void) interface_id; + (void) threshold_min; + (void) threshold_max; return -1; #endif } @@ -259,8 +267,10 @@ void net_load_balance_internal_state_activate(protocol_interface_info_entry_t *i set_req.value_pointer = &state; set_req.value_size = sizeof(bool); interface_ptr->mac_api->mlme_req(interface_ptr->mac_api, MLME_SET, &set_req); +#else + (void) interface_ptr; + (void) state; #endif - } #ifdef HAVE_RPL @@ -361,6 +371,8 @@ int8_t net_load_balance_set_max_probability(int8_t interface_id, uint8_t max_p) return load_balance_set_max_probability(interface_ptr->lb_api, max_p); #else + (void) interface_id; + (void) max_p; return -1; #endif } diff --git a/source/libNET/src/ns_net.c b/source/libNET/src/ns_net.c index 5ee8a60dc667..e369f6c37588 100644 --- a/source/libNET/src/ns_net.c +++ b/source/libNET/src/ns_net.c @@ -400,6 +400,10 @@ int8_t arm_nwk_6lowpan_gp_address_mode(int8_t interface_id, net_6lowpan_gp_addre return 0; #else + (void) interface_id; + (void) mode; + (void) short_address_base; + (void) define_new_short_address_at_DAD; return -2; #endif } @@ -895,7 +899,7 @@ int8_t arm_pana_client_key_pull(int8_t interface_id) return pana_client_key_pull(interface_id); } -int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_layer_sec_mode_e mode, uint8_t sec_level, const net_link_layer_psk_security_info_s *psk_key_info) +int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_layer_sec_mode_e mode, uint8_t sec_level, const net_link_layer_psk_security_info_s *psk_key_info) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); if (!cur || thread_info(cur) || !cur->mac_parameters || (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) == 0) { @@ -903,6 +907,9 @@ int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_la } #ifndef HAVE_6LOWPAN_ND + (void) mode; + (void) sec_level; + (void) psk_key_info; return -1; #else if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { diff --git a/source/libNET/src/socket_api.c b/source/libNET/src/socket_api.c index 65b192145dd5..2cf27829c5e5 100644 --- a/source/libNET/src/socket_api.c +++ b/source/libNET/src/socket_api.c @@ -108,6 +108,8 @@ int8_t socket_close(int8_t sid) int8_t socket_listen(int8_t socket, uint8_t backlog) { #ifdef NO_TCP + (void) socket; + (void) backlog; return -1; #else socket_t *socket_ptr = socket_pointer_get(socket); @@ -141,6 +143,9 @@ int8_t socket_listen(int8_t socket, uint8_t backlog) int8_t socket_accept(int8_t listen_socket_id, ns_address_t *addr, void (*passed_fptr)(void *)) { #ifdef NO_TCP + (void) listen_socket_id; + (void) addr; + (void) passed_fptr; return -1; #else socket_t *socket_ptr = socket_pointer_get(listen_socket_id); @@ -189,6 +194,8 @@ int8_t socket_accept(int8_t listen_socket_id, ns_address_t *addr, void (*passed_ int8_t socket_shutdown(int8_t socket, uint8_t how) { #ifdef NO_TCP + (void) socket; + (void) how; return -1; #else socket_t *socket_ptr = socket_pointer_get(socket); @@ -608,8 +615,8 @@ int8_t socket_connect(int8_t socket, ns_address_t *address, uint8_t randomly_tak socket_ptr->flags |= SOCKET_FLAG_CONNECTING; } -#endif exit: +#endif if (status != 0) { memcpy(inet_pcb->remote_address, ns_in6addr_any, 16); inet_pcb->remote_port = 0; From a126cb750d9460de90239257e345b122948d71d1 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 22 Jan 2020 13:22:44 +0200 Subject: [PATCH 50/88] ETX sampling rule update Min sampling rule is now compared to MAC radio attempts not a MAC-Data-request attempts. In link failure case will respond now faster and not need so many etx propes in 1 minute. Change-Id: Ieb1108aa19672021258eedd16484532751c82d46 --- source/Service_Libs/etx/etx.c | 22 ++++++++-------------- source/Service_Libs/etx/etx.h | 5 ++--- test/nanostack/unittest/stub/etx_stub.c | 2 +- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 6f3c671dd658..89c7ab3bf40e 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -64,11 +64,11 @@ typedef struct { uint32_t max_etx_update; uint32_t max_etx; uint16_t hysteresis; // 12 bit fraction + uint16_t init_etx_sample_count; uint8_t accum_threshold; uint8_t etx_min_sampling_time; uint8_t ext_storage_list_size; - uint8_t min_sample_count; - uint8_t init_etx_sample_count; + uint8_t min_attempts_count; bool cache_sample_requested; int8_t interface_id; } ext_info_t; @@ -81,7 +81,7 @@ static ext_info_t etx_info = { .etx_storage_list = NULL, .etx_cache_storage_list = NULL, .ext_storage_list_size = 0, - .min_sample_count = 0, + .min_attempts_count = 0, .max_etx_update = 0, .max_etx = 0xffff, .init_etx_sample_count = 1, @@ -146,7 +146,6 @@ static void etx_cache_entry_init(uint8_t attribute_index) storage->attempts_count = 0; storage->etx_timer = etx_info.etx_min_sampling_time; storage->received_acks = 0; - storage->sample_count = 0; } static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *entry, uint16_t time_update) @@ -161,9 +160,9 @@ static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *en if (entry->etx_samples > etx_info.init_etx_sample_count) { //Slower ETX update phase - if (storage->sample_count >= etx_info.min_sample_count) { + if (storage->attempts_count >= etx_info.min_attempts_count) { - if (storage->etx_timer == 0 || storage->sample_count == 0xff) { + if (storage->etx_timer == 0 || storage->attempts_count == 0xffff || storage->received_acks == 0xff) { //Got least min sample in requested time or max possible sample return true; } @@ -187,7 +186,6 @@ static etx_sample_storage_t *etx_cache_sample_update(uint8_t attribute_index, ui if (ack_rx) { storage->received_acks++; } - storage->sample_count++; return storage; } @@ -223,10 +221,6 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ etx_sample_storage_t *storage = etx_cache_sample_update(attribute_index, attempts, success); entry->accumulated_failures = 0; - if (!success && entry->etx_samples < etx_info.init_etx_sample_count) { - storage->sample_count = etx_info.init_etx_sample_count; //Force stop probing if any init fail totally - } - if (!etx_update_possible(storage, entry, 0)) { return; } @@ -613,14 +607,14 @@ bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size) } -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count) +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_attempts_count, uint8_t init_etx_sample_count) { //No ini ETX allocation done yet if (etx_info.ext_storage_list_size == 0) { return false; } - if (min_wait_time || etx_min_sample_count) { + if (min_wait_time || etx_min_attempts_count) { if (init_etx_sample_count == 0) { return false; } @@ -647,7 +641,7 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_ etx_info.etx_cache_storage_list = NULL; } - etx_info.min_sample_count = etx_min_sample_count; + etx_info.min_attempts_count = etx_min_attempts_count; etx_info.etx_min_sampling_time = min_wait_time; etx_info.init_etx_sample_count = init_etx_sample_count; diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index a820ee1b14ea..7b89634c3bed 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -64,7 +64,6 @@ typedef struct etx_sample_storage_s { uint16_t attempts_count; /*!< TX attempt count */ uint8_t etx_timer; /*!< Count down from configured value 0 means that ETX Update is possible done again*/ uint8_t received_acks; /*!< Received ACK's */ - uint8_t sample_count; /*!< Finished TX count */ } etx_sample_storage_t; /** @@ -266,14 +265,14 @@ void etx_cache_timer(int8_t interface_id, uint16_t seconds_update); * ETX update will happen when min wait time is reached and also reached min etx sample count. * * \param min_wait_time how many seconds must wait before do new ETX - * \param etx_min_sample_count define how many completed TX process must be done for new ETX. Min accepted value is 4. + * \param etx_min_attempts_count define how many TX attempts process must be done for new ETX. Min accepted value is 4. * \param init_etx_sample_count How Many sample is need to init etx calculate * * \return true Enable is OK * \return false Memory allocation fail * */ -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count); +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_attempts_count, uint8_t init_etx_sample_count); /** diff --git a/test/nanostack/unittest/stub/etx_stub.c b/test/nanostack/unittest/stub/etx_stub.c index 49f6a9743e60..3f0ecb643665 100644 --- a/test/nanostack/unittest/stub/etx_stub.c +++ b/test/nanostack/unittest/stub/etx_stub.c @@ -87,7 +87,7 @@ void etx_cache_timer(int8_t interface_id, uint16_t seconds_update) } -bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_sample_count, uint8_t init_etx_sample_count) +bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_attempts_count, uint8_t init_etx_sample_count) { return true; } From 2ff90e6c0f43c6e83ee1a21947147840147c341e Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Fri, 24 Jan 2020 14:49:31 +0200 Subject: [PATCH 51/88] Configure TXRX slot length using given datarate (#2275) --- nanostack/platform/arm_hal_phy.h | 3 +- source/MAC/IEEE802_15_4/mac_defines.h | 1 + source/MAC/IEEE802_15_4/mac_fhss_callbacks.c | 9 ++- source/MAC/IEEE802_15_4/mac_mlme.c | 3 +- source/Service_Libs/fhss/fhss_ws.c | 62 +++++++++++++++++--- source/Service_Libs/fhss/fhss_ws.h | 6 +- 6 files changed, 69 insertions(+), 15 deletions(-) diff --git a/nanostack/platform/arm_hal_phy.h b/nanostack/platform/arm_hal_phy.h index 56e9591fe268..96ea55016f84 100644 --- a/nanostack/platform/arm_hal_phy.h +++ b/nanostack/platform/arm_hal_phy.h @@ -161,7 +161,8 @@ typedef enum { CHANNEL_PAGE_5 = 5, ///< Page 5 CHANNEL_PAGE_6 = 6, ///< Page 6 CHANNEL_PAGE_9 = 9, ///< Page 9 - CHANNEL_PAGE_10 = 10 ///< Page 10 + CHANNEL_PAGE_10 = 10, ///< Page 10 + CHANNEL_PAGE_UNDEFINED ///< Undefined } channel_page_e; /** Modulation index */ diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index e7d1babeaa0d..acc45a678808 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -245,6 +245,7 @@ typedef struct protocol_interface_rf_mac_setup { uint32_t mlme_tick_count; uint32_t symbol_rate; uint32_t symbol_time_us; + uint32_t datarate; uint8_t max_ED; uint16_t mlme_ED_counter; mac_tx_status_t mac_tx_status; diff --git a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c index 3f09ca01baf7..fd56ecbd74a7 100644 --- a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c +++ b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c @@ -57,8 +57,13 @@ uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api) if (!mac_setup) { return 0; } - uint32_t datarate = dev_get_phy_datarate(mac_setup->dev_driver->phy_driver, mac_setup->mac_channel_list.channel_page); - // If datarate is not set, use default 250kbit/s. + uint32_t datarate = 0; + // When channel page is set, ask data rate directly from PHY driver, otherwise use data rate configured to MAC. Ultimately, use default value instead 0. + if (mac_setup->mac_channel_list.channel_page != CHANNEL_PAGE_UNDEFINED) { + datarate = dev_get_phy_datarate(mac_setup->dev_driver->phy_driver, mac_setup->mac_channel_list.channel_page); + } else if (mac_setup->datarate) { + datarate = mac_setup->datarate; + } if (!datarate) { datarate = 250000; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index 478b8a9d88ee..b091da2a85f0 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -783,7 +783,7 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) set_req->value_pointer); mac_mlme_set_symbol_rate(rf_mac_setup); phy_rf_channel_configuration_s *config_params = (phy_rf_channel_configuration_s *)set_req->value_pointer; - (void) config_params; // unused variable if traces disabled + rf_mac_setup->datarate = config_params->datarate; tr_info("RF config update:"); tr_info("Frequency(ch0): %"PRIu32"Hz", config_params->channel_0_center_frequency); tr_info("Channel spacing: %"PRIu32"Hz", config_params->channel_spacing); @@ -1091,6 +1091,7 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a entry->aUnitBackoffPeriod = 20; //This can be different in some Platform 20 comes from 12-symbol turnaround and 8 symbol CCA read entry->number_of_csma_ca_periods = MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS; entry->multi_cca_interval = MAC_DEFAULT_CSMA_MULTI_CCA_INTERVAL; + entry->mac_channel_list.channel_page = CHANNEL_PAGE_UNDEFINED; if (mac_sec_mib_init(entry, storage_sizes) != 0) { mac_mlme_data_base_deallocate(entry); diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index d8c07b8a738f..f480cb0b9560 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -83,7 +83,7 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure); static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay); static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure); -static uint32_t fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure); +static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure); // This function supports rounding up static int64_t divide_integer(int64_t dividend, int32_t divisor) @@ -150,7 +150,6 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati fhss_ws_set_hop_count(fhss_struct, 0xff); fhss_struct->rx_channel = fhss_configuration->unicast_fixed_channel; fhss_struct->ws->min_synch_interval = DEFAULT_MIN_SYNCH_INTERVAL; - fhss_set_txrx_slot_length(fhss_struct); ns_list_init(&fhss_struct->fhss_failed_tx_list); return fhss_struct; } @@ -173,14 +172,46 @@ static int fhss_ws_manage_channel_table_allocation(fhss_structure_t *fhss_struct return 0; } -static uint32_t fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) +static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) { - uint32_t number_of_tx_slots = ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / WS_MAX_TXRX_SLOT_LEN_MS) / 2; + // No broadcast schedule, no TX slots + if (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval == 0 || fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval == 0) { + return; + } + uint32_t txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS; + if (fhss_structure->callbacks.read_datarate) { + /* Calculate minimum TX slot length which can fit optimal packet length twice. + * Twice, because 0, 1, 4, 5... hop starts transmission at the beginning of TX slot and 2, 3, 6, 7... hop at the middle of TX slot + * + * hop 0 + * tx'ing | | | | | | + * | BC | RX | TX | RX | TX | RX | TX | BC | + * hop 1 + * tx'ing | | | | | | + * | BC | TX | RX | TX | RX | TX | RX | BC | + * hop 2 + * tx'ing | | | | | | + * | BC | RX | TX | RX | TX | RX | TX | BC | + * hop 3 + * tx'ing | | | | | | + * | BC | TX | RX | TX | RX | TX | RX | BC | + */ + uint32_t datarate = fhss_structure->callbacks.read_datarate(fhss_structure->fhss_api); + if (datarate) { + txrx_slot_length_ms_tmp = ((OPTIMAL_PACKET_LENGTH * 2) * (8000000 / datarate)) / 1000; + } + } + uint32_t number_of_tx_slots = ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / txrx_slot_length_ms_tmp) / 2; if (!number_of_tx_slots) { - return 0; + return; } fhss_structure->ws->txrx_slot_length_ms = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / (number_of_tx_slots * 2); - return number_of_tx_slots; + tr_info("TX slot length: %"PRIu32"ms", fhss_structure->ws->txrx_slot_length_ms); +} + +static uint32_t fhss_get_number_of_tx_slots(fhss_structure_t *fhss_structure) +{ + return ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / fhss_structure->ws->txrx_slot_length_ms) / 2; } static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure) @@ -397,7 +428,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat if (fhss_state == FHSS_SYNCHRONIZED) { uint32_t fhss_broadcast_interval = fhss_structure->ws->fhss_configuration.fhss_broadcast_interval; uint8_t fhss_bc_dwell_interval = fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval; - + fhss_set_txrx_slot_length(fhss_structure); // Start broadcast schedule when BC intervals are known if (fhss_broadcast_interval && fhss_bc_dwell_interval) { fhss_broadcast_handler(fhss_structure->fhss_api, 0); @@ -537,7 +568,7 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure) if (fhss_structure->ws->is_on_bc_channel == true) { return true; } - uint32_t number_of_tx_slots = fhss_set_txrx_slot_length(fhss_structure); + uint32_t number_of_tx_slots = fhss_get_number_of_tx_slots(fhss_structure); // Allow transmission when broadcast interval is very short comparing to MAX slot length if (!number_of_tx_slots) { return true; @@ -545,9 +576,22 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure) uint32_t remaining_time_ms = get_remaining_slots_us(fhss_structure, fhss_broadcast_handler, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval)) / 1000; uint32_t tx_slot_begin_ms = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (fhss_structure->ws->txrx_slot_length_ms * (fhss_structure->own_hop & 1)); + /* Return false when our first TX slot has not yet started + * |------remaining_time_ms---| + * | + * v + * | BC | RX | TX | RX | TX | RX | TX | BC | + */ + if (tx_slot_begin_ms < remaining_time_ms) { + return false; + } tx_slot_begin_ms = tx_slot_begin_ms - (((tx_slot_begin_ms - remaining_time_ms) / (2 * fhss_structure->ws->txrx_slot_length_ms)) * (2 * fhss_structure->ws->txrx_slot_length_ms)); uint32_t rx_slot_begin_ms = tx_slot_begin_ms - fhss_structure->ws->txrx_slot_length_ms; - // Check if we are currently on TX slot. + /* Check if we are currently on TX slot. + * | | | + * v v v + * | BC | RX | TX | RX | TX | RX | TX | BC | + */ if ((remaining_time_ms <= tx_slot_begin_ms) && (remaining_time_ms > rx_slot_begin_ms)) { return true; } diff --git a/source/Service_Libs/fhss/fhss_ws.h b/source/Service_Libs/fhss/fhss_ws.h index 917b599878f9..d16643a780e4 100644 --- a/source/Service_Libs/fhss/fhss_ws.h +++ b/source/Service_Libs/fhss/fhss_ws.h @@ -21,8 +21,10 @@ * At least 4 channel retries must be used: (Initial channel + WS_NUMBER_OF_CHANNEL_RETRIES) * MAC attempts = (1+4)*4=20 attempts */ #define WS_NUMBER_OF_CHANNEL_RETRIES 4 -//TX/RX slot length in milliseconds -#define WS_MAX_TXRX_SLOT_LEN_MS 100 +// TX slot length is optimised to this packet length +#define OPTIMAL_PACKET_LENGTH 500 +// Default TX/RX slot length in milliseconds. Is used when datarate is not given by PHY. +#define WS_TXRX_SLOT_LEN_MS 100 // Default minimum broadcast synchronization interval in seconds #define DEFAULT_MIN_SYNCH_INTERVAL 60 // Drift compensation allowed if at least SYNCH_COMPENSATION_MIN_INTERVAL (seconds) since last synchronization From a043f8dc30118208d3ba073bf47e442d498d9d6c Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 21 Jan 2020 14:30:20 +0200 Subject: [PATCH 52/88] Wi-sun FHSS Management update Added validation for given dwell time that it must by min 15 when it is not 0. Wi-sun boot is now only activated when FHSS config is changed. Change-Id: I9462d91f8185611b16b2b899b6e195f854cc455c --- source/6LoWPAN/ws/ws_management_api.c | 77 +++++++++++++++++++++------ 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index e8be8dac519d..63f7322326a9 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -220,20 +220,32 @@ int ws_management_fhss_timing_configure( if (!cur || !ws_info(cur)) { return -1; } - if (fhss_uc_dwell_interval > 0) { + + if (fhss_uc_dwell_interval && fhss_uc_dwell_interval < 15) { + return -2; + } + + if (fhss_bc_dwell_interval && fhss_bc_dwell_interval < 15) { + return -2; + } + + bool updated_configure = false; + + if (fhss_uc_dwell_interval > 0 && cur->ws_info->fhss_uc_dwell_interval != fhss_uc_dwell_interval) { cur->ws_info->fhss_uc_dwell_interval = fhss_uc_dwell_interval; + updated_configure = true; } - if (fhss_broadcast_interval > 0) { + if (fhss_broadcast_interval > 0 && cur->ws_info->fhss_bc_interval != fhss_broadcast_interval) { cur->ws_info->fhss_bc_interval = fhss_broadcast_interval; - + updated_configure = true; } - if (fhss_bc_dwell_interval > 0) { + if (fhss_bc_dwell_interval > 0 && cur->ws_info->fhss_bc_dwell_interval != fhss_bc_dwell_interval) { cur->ws_info->fhss_bc_dwell_interval = fhss_bc_dwell_interval; - + updated_configure = true; } // if settings change reset_restart for the settings needed - if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { + if (updated_configure && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { // bootstrap active need to restart ws_bootstrap_restart(interface_id); } @@ -259,23 +271,38 @@ int ws_management_fhss_unicast_channel_function_configure( return -2; } + if (dwell_interval && dwell_interval < 15) { + return -2; + } + if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) { fixed_channel = 0; tr_warn("Fixed channel not configured. Set to 0"); } + bool updated_config = false; + + if (cur->ws_info->fhss_uc_channel_function != channel_function) { + cur->ws_info->fhss_uc_channel_function = channel_function; + updated_config = true; + } - cur->ws_info->fhss_uc_channel_function = channel_function; if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) { - cur->ws_info->fhss_uc_fixed_channel = fixed_channel; + if (cur->ws_info->fhss_uc_fixed_channel != fixed_channel) { + cur->ws_info->fhss_uc_fixed_channel = fixed_channel; + updated_config = true; + } } else { cur->ws_info->fhss_uc_fixed_channel = 0xffff; } - cur->ws_info->fhss_uc_dwell_interval = dwell_interval; + if (dwell_interval && cur->ws_info->fhss_uc_dwell_interval != dwell_interval) { + cur->ws_info->fhss_uc_dwell_interval = dwell_interval; + updated_config = true; + } // if settings change reset_restart for the settings needed - if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { + if (updated_config && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { // bootstrap active need to restart ws_bootstrap_restart(interface_id); } @@ -303,23 +330,43 @@ int ws_management_fhss_broadcast_channel_function_configure( return -2; } + if (dwell_interval && dwell_interval < 15) { + return -2; + } + if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) { fixed_channel = 0; tr_warn("Fixed channel not configured. Set to 0"); } - cur->ws_info->fhss_bc_channel_function = channel_function; + bool updated_config = false; + + if (cur->ws_info->fhss_bc_channel_function != channel_function) { + cur->ws_info->fhss_bc_channel_function = channel_function; + updated_config = true; + } + if (cur->ws_info->fhss_bc_channel_function == WS_FIXED_CHANNEL) { - cur->ws_info->fhss_bc_fixed_channel = fixed_channel; + if (cur->ws_info->fhss_bc_fixed_channel != fixed_channel) { + cur->ws_info->fhss_bc_fixed_channel = fixed_channel; + updated_config = true; + } } else { cur->ws_info->fhss_bc_fixed_channel = 0xffff; } - cur->ws_info->fhss_bc_dwell_interval = dwell_interval; - cur->ws_info->fhss_bc_interval = broadcast_interval; + if (dwell_interval > 0 && cur->ws_info->fhss_bc_dwell_interval != dwell_interval) { + cur->ws_info->fhss_bc_dwell_interval = dwell_interval; + updated_config = true; + } + + if (broadcast_interval > 0 && cur->ws_info->fhss_bc_interval != broadcast_interval) { + cur->ws_info->fhss_bc_interval = broadcast_interval; + updated_config = true; + } // if settings change reset_restart for the settings needed - if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { + if (updated_config && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { // bootstrap active need to restart ws_bootstrap_restart(interface_id); } From 7b6bcca842d6ed1de1a83b1dde25b27278f740c0 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Mon, 27 Jan 2020 15:56:09 +0200 Subject: [PATCH 53/88] Added TX/RX bytes in PHY statistics (#2281) --- nanostack/platform/arm_hal_phy.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nanostack/platform/arm_hal_phy.h b/nanostack/platform/arm_hal_phy.h index 96ea55016f84..ab53b5942cb0 100644 --- a/nanostack/platform/arm_hal_phy.h +++ b/nanostack/platform/arm_hal_phy.h @@ -195,6 +195,8 @@ typedef struct phy_rf_statistics_s { uint32_t rx_timeouts; ///< reception timeouts uint64_t tx_active_time; ///< transmission active time uint64_t rx_active_time; ///< reception active time + uint32_t tx_bytes; ///< transmitted bytes + uint32_t rx_bytes; ///< received bytes } phy_rf_statistics_s; /** Virtual data request */ From 427743f718952c4c17032e194abe881ca2438ce6 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Fri, 24 Jan 2020 12:06:20 +0200 Subject: [PATCH 54/88] ETX and Source route validation update RPL downward route link capable limit from 8.0 to 4.0. This will fix broken link at SRC route. Return 0 if real is unknow. RPL parent changes and ETX changes use same dynamic timer start for new neighbour or better ETX. Change-Id: I9b7d22a45a96d100f9695184896e636f17804fbf --- source/6LoWPAN/adaptation_interface.c | 2 +- source/6LoWPAN/ws/ws_bootstrap.c | 16 +++---- source/RPL/rpl_control.c | 13 ++++-- source/RPL/rpl_policy.c | 2 +- source/RPL/rpl_upward.c | 24 ++++++----- source/RPL/rpl_upward.h | 4 +- source/Service_Libs/etx/etx.c | 43 +++---------------- source/Service_Libs/etx/etx.h | 11 ----- .../unittest/service_libs/etx/etxtest.cpp | 4 -- .../unittest/service_libs/etx/test_etx.c | 33 -------------- .../unittest/service_libs/etx/test_etx.h | 1 - test/nanostack/unittest/stub/etx_stub.c | 5 --- .../nanostack/unittest/stub/rpl_upward_stub.c | 4 +- 13 files changed, 40 insertions(+), 122 deletions(-) diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index a4bc2ebea7bf..99636719d9d5 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -1260,7 +1260,7 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c } #ifdef HAVE_RPL - if (confirm->status == MLME_TX_NO_ACK) { + if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) { if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); } diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index ed7cee4a9e07..e81890227cec 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -648,7 +648,6 @@ static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entr uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr_type, const uint8_t *addr_ptr) { - uint16_t etx; if (!addr_ptr || !interface) { return 0; } @@ -667,13 +666,7 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr return 0xffff; } - etx = etx_local_etx_read(interface->id, attribute_index); - if (etx == 0) { - return 0xffff; - } - - //tr_debug("ws_etx_read etx:%d", etx); - return etx; + return etx_local_etx_read(interface->id, attribute_index);; } bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq) { @@ -2564,10 +2557,11 @@ static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entr uint16_t etx = etx_local_etx_read(cur->id, mac_neighbor->index); if (etx == 0) { - etx = 0xffff; + etx = WS_ETX_MAX; //SET maxium value here if ETX is unknown + } else { + //Scale to 128 based ETX (local read retur 0x100 - 0xffff + etx = etx >> 1; } - //Scale to 128 based ETX (local read retur 0x100 - 0xffff - etx = etx >> 1; return ws_neighbor->routing_cost + etx; } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 5a05b010f71f..1dfd0fd65735 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -376,19 +376,24 @@ static void rpl_control_addr_notifier(struct protocol_interface_info_entry *inte static void rpl_control_etx_change_callback(int8_t nwk_id, uint16_t previous_etx, uint16_t current_etx, uint8_t attribute_index) { - (void)previous_etx; - (void)current_etx; protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(nwk_id); if (!cur || !cur->rpl_domain) { return; } + // ETX is "better" if now lower, or previous was "unknown" and new isn't infinite + bool better = current_etx < previous_etx || (previous_etx == 0 && current_etx != 0xffff); + rpl_domain_t *domain = cur->rpl_domain; uint16_t delay = rpl_policy_etx_change_parent_selection_delay(domain); - tr_debug("Triggering parent selection due to ETX change on neigh index %u, etx %u", attribute_index, current_etx); + tr_debug("Triggering parent selection due to ETX %s on neigh index %u, etx %u", better ? "better" : "worse", attribute_index, current_etx); + rpl_dodag_t *dodag = NULL; ns_list_foreach(rpl_instance_t, instance, &domain->instances) { - rpl_instance_trigger_parent_selection(instance, delay); + if (better) { + dodag = rpl_instance_current_dodag(instance); + } + rpl_instance_trigger_parent_selection(instance, delay, dodag); if (rpl_instance_am_root(instance)) { rpl_downward_paths_invalidate(instance); } diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index ec581c8bb421..d95c35e6807b 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -147,7 +147,7 @@ int8_t rpl_policy_dao_retry_count() /* Given the next-hop address from a source routing header, which interface, * if any, should we assume that next hop is on? */ -#define ETX_SRH_THRESHOLD 0x800 /* 8.8 fixed-point, so 4 */ +#define ETX_SRH_THRESHOLD 0x400 /* 8.8 fixed-point, so 4 */ int8_t rpl_policy_srh_next_hop_interface(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop) { if (domain->non_storing_downstream_interface != -1) { diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 4a41b84ed1d5..dae9ca5da095 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -352,8 +352,16 @@ void rpl_instance_force_leaf(rpl_instance_t *instance) instance->current_rank = RPL_RANK_INFINITE; } -void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay) +void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay, rpl_dodag_t *dodag) { + /* When "improving", let us have a minimum trigger time based on Imin, for large networks */ + if (dodag) { + //Convert imin 100ms tick to seconds + uint16_t i_min_delay = dodag->dio_timer_params.Imin / 10; + if (i_min_delay > delay) { + delay = i_min_delay; + } + } if (instance->parent_selection_timer == 0 || instance->parent_selection_timer > delay) { instance->parent_selection_timer = randLIB_randomise_base(delay, 0x8000, 0x999A) /* Random between delay * 1.0-1.2 */; tr_debug("Timed parent triggered %u", instance->parent_selection_timer); @@ -585,7 +593,7 @@ void rpl_delete_dodag_version(rpl_dodag_version_t *version) // triggering poison immediately. // Give parent selection a chance to select another version (but will it have any info on-hand?) instance->current_dodag_version = NULL; - rpl_instance_trigger_parent_selection(instance, 5); + rpl_instance_trigger_parent_selection(instance, 5, NULL); } ns_list_foreach_safe(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { @@ -1278,18 +1286,12 @@ bool rpl_instance_purge(rpl_instance_t *instance) return false; } -void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag) +void rpl_instance_neighbours_changed(rpl_instance_t *instance, rpl_dodag_t *dodag) { instance->neighbours_changed = true; uint16_t delay = rpl_policy_dio_parent_selection_delay(instance->domain); - if (dodag) { - //Convert imin 100ms tick to seconds - uint16_t i_min_delay = dodag->dio_timer_params.Imin / 10; - if (i_min_delay > delay) { - delay = i_min_delay; - } - } - rpl_instance_trigger_parent_selection(instance, delay); + + rpl_instance_trigger_parent_selection(instance, delay, dodag); } static void rpl_instance_remove_parents(rpl_instance_t *instance) diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index ebf386f8d42b..b3b51b38bc60 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -78,7 +78,7 @@ void rpl_instance_increment_dtsn(rpl_instance_t *instance); void rpl_dodag_set_pref(rpl_dodag_t *dodag, uint8_t pref); void rpl_instance_poison(rpl_instance_t *instance, uint8_t count); void rpl_instance_force_leaf(rpl_instance_t *instance); -void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay); +void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay, rpl_dodag_t *dodag); void rpl_instance_remove_interface(rpl_instance_t *instance, int8_t if_id); void rpl_instance_dio_trigger(rpl_instance_t *instance, struct protocol_interface_info_entry *cur, const uint8_t *addr); void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair); @@ -147,7 +147,7 @@ bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn); rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour); -void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag); +void rpl_instance_neighbours_changed(rpl_instance_t *instance, rpl_dodag_t *dodag); void rpl_instance_run_parent_selection(rpl_instance_t *instance); void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn); diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 89c7ab3bf40e..639490981a62 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -394,8 +394,7 @@ uint16_t etx_local_etx_read(int8_t interface_id, uint8_t attribute_index) if (etx_info.cache_sample_requested && entry->etx_samples < etx_info.init_etx_sample_count) { if (!entry->etx_samples) { - //Return configured MAX value - return etx_info.max_etx >> 4; + return 0; } } @@ -455,7 +454,12 @@ uint16_t etx_lqi_dbm_update(int8_t interface_id, uint8_t lqi, int8_t dbm, uint8_ if (!entry->etx) { etx = etx_dbm_lqi_calc(lqi, dbm); entry->etx = etx; + entry->stored_diff_etx = etx; entry->tmp_etx = true; + if (etx_info.callback_ptr) { + etx_info.callback_ptr(etx_info.interface_id, 0, entry->etx >> 4, + attribute_index); + } } // If local ETX has been calculated without remote incoming IDR and // remote incoming IDR is available update it by remote incoming IDR value @@ -470,11 +474,7 @@ uint16_t etx_lqi_dbm_update(int8_t interface_id, uint8_t lqi, int8_t dbm, uint8_ entry->etx = etx >> 12; local_incoming_idr >>= 4; - } - - // If local ETX has been calculated indicates new neighbor - if (etx) { - etx_neighbor_add(interface_id, attribute_index); + etx_value_change_callback_needed_check(entry->etx, &(entry->stored_diff_etx), entry->accumulated_failures, attribute_index); } } @@ -808,35 +808,6 @@ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index) } } -/** - * \brief A function to add ETX neighbor - * - * Notifies ETX module that neighbor has been added. Calls ETX value change callback - * if that is set. - * - * \param mac64_addr_ptr long MAC address - * - */ -void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index) -{ - - //tr_debug("Add attribute %u", attribute_index); - uint16_t stored_diff_etx; - etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index); - if (entry && etx_info.callback_ptr) { - // Gets table entry - - if (entry->etx) { - stored_diff_etx = entry->stored_diff_etx; - if (!stored_diff_etx) { - stored_diff_etx = entry->etx; - } - etx_info.callback_ptr(etx_info.interface_id, stored_diff_etx >> 4, entry->etx >> 4, - attribute_index); - } - } -} - void etx_cache_timer(int8_t interface_id, uint16_t seconds_update) { if (!etx_info.cache_sample_requested) { diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index 7b89634c3bed..c785cc5c9830 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -236,17 +236,6 @@ uint8_t etx_accum_failures_callback_register(nwk_interface_id nwk_id, int8_t int */ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index); -/** - * \brief A function to add ETX neighbor - * - * Notifies ETX module that neighbor has been added. Calls ETX value change callback - * if that is set. - * - * \param attribute_index Neighbour attribute index - * - */ -void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index); - /** * \brief A function for update cached ETX calculation * diff --git a/test/nanostack/unittest/service_libs/etx/etxtest.cpp b/test/nanostack/unittest/service_libs/etx/etxtest.cpp index 4da6f85c7588..7546cc316301 100644 --- a/test/nanostack/unittest/service_libs/etx/etxtest.cpp +++ b/test/nanostack/unittest/service_libs/etx/etxtest.cpp @@ -111,7 +111,3 @@ TEST(ETX, test_ETX_etx_neighbor_remove_1) CHECK(test_ETX_etx_neighbor_remove_1()); } -TEST(ETX, test_ETX_etx_neighbor_add_1) -{ - CHECK(test_ETX_etx_neighbor_add_1()); -} diff --git a/test/nanostack/unittest/service_libs/etx/test_etx.c b/test/nanostack/unittest/service_libs/etx/test_etx.c index a781f0a6954a..d9bd6b0bc88a 100644 --- a/test/nanostack/unittest/service_libs/etx/test_etx.c +++ b/test/nanostack/unittest/service_libs/etx/test_etx.c @@ -754,36 +754,3 @@ bool test_ETX_etx_neighbor_remove_1() etx_storage_list_allocate(0, 0); return true; } - -bool test_ETX_etx_neighbor_add_1() -{ - test_etx_set_protocol(); - nsdynmemlib_stub.returnCounter = 1; - etx_storage_list_allocate(0, 10); - etx_storage_t *test_entry = etx_storage_entry_get(0, 0); - uint8_t i; - uint8_t attempts; - bool success; - double etx = 1; - double output_etx; - test_entry->etx = 1 << 12; - - memset(change_ind_handler_values, 0, sizeof(change_ind_handler_values)); - change_ind_handler_index = 0; - - // 3/1 ETX - attempts = 3; - success = 1; - - (void) etx_value_change_callback_register(IF_6LoWPAN, 0, 128, etx_value_change_ind_handler); - - etx_neighbor_add(0, 0); - - if ((change_ind_handler_values[0].current_etx != 0x0100) || - (change_ind_handler_values[0].previous_etx != 0x0100)) { - return false; - } - - etx_storage_list_allocate(0, 0); - return true; -} diff --git a/test/nanostack/unittest/service_libs/etx/test_etx.h b/test/nanostack/unittest/service_libs/etx/test_etx.h index f873eea85ccc..252d673fd6a6 100644 --- a/test/nanostack/unittest/service_libs/etx/test_etx.h +++ b/test/nanostack/unittest/service_libs/etx/test_etx.h @@ -40,7 +40,6 @@ bool test_ETX_etx_lqi_dbm_update_2(); bool test_ETX_etx_value_change_callback_register_1(); bool test_ETX_etx_accum_failures_callback_register_1(); bool test_ETX_etx_neighbor_remove_1(); -bool test_ETX_etx_neighbor_add_1(); #ifdef __cplusplus } diff --git a/test/nanostack/unittest/stub/etx_stub.c b/test/nanostack/unittest/stub/etx_stub.c index 3f0ecb643665..e9738d5c9895 100644 --- a/test/nanostack/unittest/stub/etx_stub.c +++ b/test/nanostack/unittest/stub/etx_stub.c @@ -67,11 +67,6 @@ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index) { } -void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index) -{ - -} - bool etx_storage_list_allocate(int8_t interface_id, uint8_t etx_storage_size) { return true; diff --git a/test/nanostack/unittest/stub/rpl_upward_stub.c b/test/nanostack/unittest/stub/rpl_upward_stub.c index 5966ada3f49e..0cc91ac86c35 100644 --- a/test/nanostack/unittest/stub/rpl_upward_stub.c +++ b/test/nanostack/unittest/stub/rpl_upward_stub.c @@ -169,7 +169,7 @@ void rpl_instance_force_leaf(rpl_instance_t *instance) { } -void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay) +void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t delay, rpl_dodag_t *dodag) { } @@ -393,7 +393,7 @@ bool rpl_instance_purge(rpl_instance_t *instance) return false; } -void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag) +void rpl_instance_neighbours_changed(rpl_instance_t *instance, rpl_dodag_t *dodag) { } From 9fcf718d22db34899fda2e6a8ec8109bb1cace87 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Tue, 28 Jan 2020 13:59:51 +0200 Subject: [PATCH 55/88] Updated FHSS optimal packet length to 300 bytes (#2282) * Check if TX slot setting is too high and use default instead * Fixed warning caused by debug trace --- source/Service_Libs/fhss/fhss_ws.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index f480cb0b9560..50c330f88aea 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -199,6 +199,11 @@ static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) uint32_t datarate = fhss_structure->callbacks.read_datarate(fhss_structure->fhss_api); if (datarate) { txrx_slot_length_ms_tmp = ((OPTIMAL_PACKET_LENGTH * 2) * (8000000 / datarate)) / 1000; + // Do not allow using too high TX slot length. + if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS) { + tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS); + txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS; + } } } uint32_t number_of_tx_slots = ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / txrx_slot_length_ms_tmp) / 2; From 5642a4fe7491f0e60ca8dff8a369485f9da92403 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 30 Jan 2020 12:47:15 +0200 Subject: [PATCH 56/88] Free TX failed list when FHSS deleted (#2285) --- source/Service_Libs/fhss/fhss_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Service_Libs/fhss/fhss_common.c b/source/Service_Libs/fhss/fhss_common.c index 25cd4b8b821d..0d9dc7c505bc 100644 --- a/source/Service_Libs/fhss/fhss_common.c +++ b/source/Service_Libs/fhss/fhss_common.c @@ -116,6 +116,7 @@ int8_t fhss_disable(fhss_structure_t *fhss_structure) ns_dyn_mem_free(fhss_structure->ws->tr51_channel_table); ns_dyn_mem_free(fhss_structure->ws->tr51_output_table); ns_dyn_mem_free(fhss_structure->ws); + fhss_failed_list_free(fhss_structure); ns_dyn_mem_free(fhss_structure); fhss_struct = 0; return 0; From e306dc5adb6b3df99f5b65240ac29d0710c817a7 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 30 Jan 2020 11:47:11 +0200 Subject: [PATCH 57/88] Removed extra ";" Change-Id: If928fc97fa7cf18fca24a404a2b465957228545d --- source/6LoWPAN/ws/ws_bootstrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index e81890227cec..6ec98426c0b2 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -666,7 +666,7 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr return 0xffff; } - return etx_local_etx_read(interface->id, attribute_index);; + return etx_local_etx_read(interface->id, attribute_index); } bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq) { From 8cc0ff508bb0ea6daa386de01d37abed62e070d9 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 30 Jan 2020 15:45:06 +0200 Subject: [PATCH 58/88] Disabled temporarily tx slot check for testing purposes (#2287) --- source/Service_Libs/fhss/fhss_ws.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 50c330f88aea..a09f6e763668 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -587,9 +587,10 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure) * v * | BC | RX | TX | RX | TX | RX | TX | BC | */ - if (tx_slot_begin_ms < remaining_time_ms) { - return false; - } +// Temporarily commented this check for testing purposes +// if (tx_slot_begin_ms < remaining_time_ms) { +// return false; +// } tx_slot_begin_ms = tx_slot_begin_ms - (((tx_slot_begin_ms - remaining_time_ms) / (2 * fhss_structure->ws->txrx_slot_length_ms)) * (2 * fhss_structure->ws->txrx_slot_length_ms)); uint32_t rx_slot_begin_ms = tx_slot_begin_ms - fhss_structure->ws->txrx_slot_length_ms; /* Check if we are currently on TX slot. From 35970d7ea92ce68aaaafbd1e4362f754d72ef56a Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Fri, 31 Jan 2020 09:47:37 +0200 Subject: [PATCH 59/88] Revert "Disabled temporarily tx slot check for testing purposes (#2287)" (#2289) This reverts commit 8cc0ff508bb0ea6daa386de01d37abed62e070d9. --- source/Service_Libs/fhss/fhss_ws.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index a09f6e763668..50c330f88aea 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -587,10 +587,9 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure) * v * | BC | RX | TX | RX | TX | RX | TX | BC | */ -// Temporarily commented this check for testing purposes -// if (tx_slot_begin_ms < remaining_time_ms) { -// return false; -// } + if (tx_slot_begin_ms < remaining_time_ms) { + return false; + } tx_slot_begin_ms = tx_slot_begin_ms - (((tx_slot_begin_ms - remaining_time_ms) / (2 * fhss_structure->ws->txrx_slot_length_ms)) * (2 * fhss_structure->ws->txrx_slot_length_ms)); uint32_t rx_slot_begin_ms = tx_slot_begin_ms - fhss_structure->ws->txrx_slot_length_ms; /* Check if we are currently on TX slot. From d196ffc4c563753ffb42c4dbc1d9567ed3f81b43 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Thu, 30 Jan 2020 15:55:06 +0200 Subject: [PATCH 60/88] Refactor Wi-SUN BBR stop function Created routing stop for bbr to restart the Border router state machine Now following functions are always done Cleanup DHCP server Cleanup Backbone routes Delete all generated addressess --- source/6LoWPAN/ws/ws_bbr_api.c | 50 ++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index d18d0c0ff507..b9d0e153e7d3 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -158,6 +158,7 @@ static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t } + static void ws_bbr_rpl_root_stop(void) { tr_info("RPL root stop"); @@ -165,9 +166,6 @@ static void ws_bbr_rpl_root_stop(void) rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag); protocol_6lowpan_rpl_root_dodag = NULL; } - memset(current_local_prefix, 0, 8); - memset(current_global_prefix, 0, 8); - memset(current_dodag_id, 0, 16); } static int ws_border_router_proxy_validate(int8_t interface_id, uint8_t *address) @@ -360,6 +358,31 @@ static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_ } +static void ws_bbr_routing_stop(protocol_interface_info_entry_t *cur) +{ + tr_info("BBR routing stop"); + if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) { + ws_bbr_slaac_remove(cur, current_local_prefix); + memset(current_local_prefix, 0, 8); + } + + if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) { + ws_bbr_dhcp_server_stop(cur, current_global_prefix); + if (backbone_interface_id >= 0) { + // Delete route to backbone if it exists + ipv6_route_add_with_info(current_global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0, 0); + } + memset(current_global_prefix, 0, 8); + } + + if (memcmp(current_dodag_id, ADDR_UNSPECIFIED, 8) != 0) { + ws_bbr_slaac_remove(cur, current_dodag_id); + memset(current_dodag_id, 0, 16); + } + + ws_bbr_rpl_root_stop(); +} + static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) { @@ -389,9 +412,8 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) */ if (protocol_interface_address_compare(current_dodag_id) != 0) { //DODAGID is lost need to restart - tr_warn("DODAGID lost restart RPL"); - memset(current_dodag_id, 0, 16); - ws_bbr_rpl_root_stop(); + tr_warn("DODAGID lost restart BBR"); + ws_bbr_routing_stop(cur); return; } @@ -651,18 +673,11 @@ void ws_bbr_stop(int8_t interface_id) { #ifdef HAVE_WS_BORDER_ROUTER - backbone_interface_id = -1; protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - ws_bbr_slaac_remove(cur, current_dodag_id); - if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) { - ws_bbr_slaac_remove(cur, current_local_prefix); - } - if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) { - ws_bbr_dhcp_server_stop(cur, current_global_prefix); - } + ws_bbr_routing_stop(cur); - ws_bbr_rpl_root_stop(); + backbone_interface_id = -1; current_instance_id++; #else @@ -673,11 +688,12 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options) { #ifdef HAVE_WS_BORDER_ROUTER - (void)interface_id; + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (protocol_6lowpan_rpl_root_dodag && options != configuration) { //Configuration changed delete previous setup - ws_bbr_rpl_root_stop(); + ws_bbr_routing_stop(cur); } configuration = options; return 0; From 87ee16a22b4c1ca4f078ade117f5638db6f1f2e4 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Sat, 1 Feb 2020 11:41:31 +0200 Subject: [PATCH 61/88] Call channel change after filtered out packet --- source/MAC/IEEE802_15_4/mac_pd_sap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 85c257f80c14..b937f654b970 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -920,6 +920,9 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) ERROR_HANDLER: mcps_sap_pre_parsed_frame_buffer_free(buffer); sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0); + if (rf_ptr->fhss_api) { + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0); + } return -1; } else if (message->id == MAC15_4_PD_SAP_DATA_TX_CONFIRM) { From 4f275005fbe42254cd2d2dfedd04be2ab29b345c Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Tue, 4 Feb 2020 09:57:56 +0200 Subject: [PATCH 62/88] Implemented optimal packet size test api (#2292) --- nanostack/fhss_test_api.h | 46 ++++++++++++++++++++++++ source/Service_Libs/fhss/fhss_common.h | 1 + source/Service_Libs/fhss/fhss_test_api.c | 42 ++++++++++++++++++++++ source/Service_Libs/fhss/fhss_ws.c | 6 ++-- source/Service_Libs/fhss/fhss_ws.h | 1 + sources.mk | 1 + 6 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 nanostack/fhss_test_api.h create mode 100644 source/Service_Libs/fhss/fhss_test_api.c diff --git a/nanostack/fhss_test_api.h b/nanostack/fhss_test_api.h new file mode 100644 index 000000000000..270c5a27a317 --- /dev/null +++ b/nanostack/fhss_test_api.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file fhss_test_api.h + * \brief + */ + +#ifndef FHSS_TEST_API_H +#define FHSS_TEST_API_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set optimal packet length + * + * \param fhss_api FHSS instance. + * \param packet_length Optimal packet length + * + * \return 0 Success + * \return -1 Failure + */ +int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packet_length); + +#ifdef __cplusplus +} +#endif + +#endif // FHSS_TEST_API_H diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h index 35e1d0cc4618..4d10667924ae 100644 --- a/source/Service_Libs/fhss/fhss_common.h +++ b/source/Service_Libs/fhss/fhss_common.h @@ -40,6 +40,7 @@ struct fhss_structure { int8_t fhss_event_timer; uint8_t active_fhss_events; uint16_t number_of_channels; + uint16_t optimal_packet_length; fhss_states fhss_state; uint32_t fhss_timeout; uint32_t fhss_timer; diff --git a/source/Service_Libs/fhss/fhss_test_api.c b/source/Service_Libs/fhss/fhss_test_api.c new file mode 100644 index 000000000000..15da948e2c99 --- /dev/null +++ b/source/Service_Libs/fhss/fhss_test_api.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "nsconfig.h" +#include "ns_types.h" +#include "ns_trace.h" +#include "fhss_api.h" +#include "fhss_config.h" +#include "fhss.h" +#include "fhss_common.h" +#include "fhss_ws.h" +#include "fhss_statistics.h" +#include "fhss_channel.h" +#include "channel_list.h" +#include + +#define TRACE_GROUP "fhta" + +int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packet_length) +{ + fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); + if (!fhss_structure) { + return -1; + } + fhss_structure->optimal_packet_length = packet_length; + fhss_set_txrx_slot_length(fhss_structure); + tr_debug("Setting FHSS optimal packet length to: %u", fhss_structure->optimal_packet_length); + return 0; +} diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 50c330f88aea..ab7e66016480 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -83,7 +83,6 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure); static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay); static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure); -static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure); // This function supports rounding up static int64_t divide_integer(int64_t dividend, int32_t divisor) @@ -147,6 +146,7 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); fhss_struct->ws->fhss_configuration = *fhss_configuration; fhss_struct->number_of_channels = channel_count; + fhss_struct->optimal_packet_length = OPTIMAL_PACKET_LENGTH; fhss_ws_set_hop_count(fhss_struct, 0xff); fhss_struct->rx_channel = fhss_configuration->unicast_fixed_channel; fhss_struct->ws->min_synch_interval = DEFAULT_MIN_SYNCH_INTERVAL; @@ -172,7 +172,7 @@ static int fhss_ws_manage_channel_table_allocation(fhss_structure_t *fhss_struct return 0; } -static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) +void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) { // No broadcast schedule, no TX slots if (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval == 0 || fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval == 0) { @@ -198,7 +198,7 @@ static void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) */ uint32_t datarate = fhss_structure->callbacks.read_datarate(fhss_structure->fhss_api); if (datarate) { - txrx_slot_length_ms_tmp = ((OPTIMAL_PACKET_LENGTH * 2) * (8000000 / datarate)) / 1000; + txrx_slot_length_ms_tmp = ((fhss_structure->optimal_packet_length * 2) * (8000000 / datarate)) / 1000; // Do not allow using too high TX slot length. if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS) { tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS); diff --git a/source/Service_Libs/fhss/fhss_ws.h b/source/Service_Libs/fhss/fhss_ws.h index d16643a780e4..c3d31fa67efa 100644 --- a/source/Service_Libs/fhss/fhss_ws.h +++ b/source/Service_Libs/fhss/fhss_ws.h @@ -57,5 +57,6 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]); int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration); int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count); +void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure); #endif /*FHSS_WS_H_*/ diff --git a/sources.mk b/sources.mk index 1cc99981bd29..840c51105d3d 100644 --- a/sources.mk +++ b/sources.mk @@ -136,6 +136,7 @@ SRCS += \ source/Service_Libs/fhss/fhss_common.c \ source/Service_Libs/fhss/channel_functions.c \ source/Service_Libs/fhss/channel_list.c \ + source/Service_Libs/fhss/fhss_test_api.c \ source/Service_Libs/fnv_hash/fnv_hash.c \ source/Service_Libs/hmac/hmac_sha1.c \ source/Service_Libs/ieee_802_11/ieee_802_11.c \ From fd11ffae1ada70fb0fa2a65eeb6f0492a7259daf Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Tue, 4 Feb 2020 14:06:33 +0200 Subject: [PATCH 63/88] Added HAVE_WS flag to FHSS api (#2296) --- source/Service_Libs/fhss/fhss_test_api.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/Service_Libs/fhss/fhss_test_api.c b/source/Service_Libs/fhss/fhss_test_api.c index 15da948e2c99..7b1e696ea047 100644 --- a/source/Service_Libs/fhss/fhss_test_api.c +++ b/source/Service_Libs/fhss/fhss_test_api.c @@ -31,6 +31,9 @@ int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packet_length) { + (void) fhss_api; + (void) packet_length; +#ifdef HAVE_WS fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); if (!fhss_structure) { return -1; @@ -38,5 +41,6 @@ int8_t fhss_set_optimal_packet_length(const fhss_api_t *fhss_api, uint16_t packe fhss_structure->optimal_packet_length = packet_length; fhss_set_txrx_slot_length(fhss_structure); tr_debug("Setting FHSS optimal packet length to: %u", fhss_structure->optimal_packet_length); +#endif return 0; } From f085132543a3a62a9ddfca50181e699a94930d34 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Tue, 4 Feb 2020 10:17:37 +0200 Subject: [PATCH 64/88] Made parent set size configuraple in RPL Set default parent count in Wi-SUN to be 2 --- source/6LoWPAN/ws/ws_bootstrap.c | 1 + source/6LoWPAN/ws/ws_config.h | 1 + source/RPL/rpl_control.c | 4 ++++ source/RPL/rpl_control.h | 2 ++ source/RPL/rpl_policy.c | 9 +++++++-- source/RPL/rpl_policy.h | 1 + test/nanostack/unittest/stub/rpl_control_stub.c | 4 ++++ test/nanostack/unittest/stub/rpl_policy_stub.c | 4 ++++ 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 6ec98426c0b2..9122eba73346 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2254,6 +2254,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) rpl_control_set_dio_multicast_min_config_advertisment_count(WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT); rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES); rpl_control_set_initial_dao_ack_wait(WS_MAX_DAO_INITIAL_TIMEOUT); + rpl_control_set_mrhof_parent_set_size(WS_MAX_PARENT_SET_COUNT); cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event } diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 468691d359a8..b29fbddec1e6 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -149,6 +149,7 @@ extern uint8_t DEVICE_MIN_SENS; #define WS_MAX_DAO_RETRIES 3 // With 40s, 80s, 160s, 320s, 640s #define WS_MAX_DAO_INITIAL_TIMEOUT 400 // With 40s initial value exponentially increasing #define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 0xff // Advertisment config at every MC DIO +#define WS_MAX_PARENT_SET_COUNT 2 // maximum amount of parents selected by node /* * Candidate parent list parameters diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 1dfd0fd65735..635d80547d07 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -190,6 +190,10 @@ void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms) { rpl_policy_set_initial_dao_ack_wait(timeout_in_ms); } +void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size) +{ + rpl_policy_set_mrhof_parent_set_size(parent_set_size); +} /* Send address registration to either specified address, or to non-registered address */ void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16]) diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index d3d1011fe109..4674eb76a3b9 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -168,6 +168,7 @@ void rpl_control_request_parent_link_confirmation(bool requested); void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count); void rpl_control_set_dao_retry_count(uint8_t count); void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms); +void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size); void rpl_control_register_address(struct protocol_interface_info_entry *interface, const uint8_t addr[16]); void rpl_control_address_register_done(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t status); @@ -195,6 +196,7 @@ uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain); #define rpl_control_register_address(interface, addr) ((void) 0) #define rpl_control_address_register_done(interface, ll_addr, status) ((void) 0) #define rpl_policy_mrhof_parent_set_size_get(domain) (0) +#define rpl_control_set_mrhof_parent_set_size(parent_set_size) #endif /* HAVE_RPL */ diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index d95c35e6807b..f8b25d86f19c 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -39,7 +39,7 @@ static int8_t rpl_policy_dao_retry_count_conf = 0; static int16_t rpl_policy_dao_initial_timeout_conf = 20; // Default is 2 seconds 100ms ticks static uint16_t rpl_policy_dio_validity_period_hysteresis = 0x0180; //Fixed Point 1.5 static uint8_t rpl_policy_multicast_config_min_advertisment_count = 0; - +static uint8_t rpl_policy_mrhof_parent_set_size_conf = 3; // default parent set size /* TODO - application API to control when to join new instances / DODAGs * @@ -326,11 +326,16 @@ uint_fast8_t rpl_policy_of0_max_backup_successors(const rpl_domain_t *domain) return 1; } +void rpl_policy_set_mrhof_parent_set_size(uint8_t parent_set_size) +{ + rpl_policy_mrhof_parent_set_size_conf = parent_set_size; +} + uint_fast8_t rpl_policy_mrhof_parent_set_size(const rpl_domain_t *domain) { (void)domain; - return 3; + return rpl_policy_mrhof_parent_set_size_conf; } uint16_t rpl_policy_mrhof_max_rank_stretch_for_extra_parents(const rpl_domain_t *domain) diff --git a/source/RPL/rpl_policy.h b/source/RPL/rpl_policy.h index c51adc81cd12..13e25c492ca5 100644 --- a/source/RPL/rpl_policy.h +++ b/source/RPL/rpl_policy.h @@ -59,6 +59,7 @@ uint_fast8_t rpl_policy_of0_rank_factor(const rpl_domain_t *domain); bool rpl_policy_of0_dodag_preference_supersedes_grounded(const rpl_domain_t *domain); uint_fast8_t rpl_policy_of0_max_backup_successors(const rpl_domain_t *domain); +void rpl_policy_set_mrhof_parent_set_size(uint8_t parent_set_size); uint_fast8_t rpl_policy_mrhof_parent_set_size(const rpl_domain_t *domain); uint16_t rpl_policy_mrhof_max_link_metric(const rpl_domain_t *domain); uint16_t rpl_policy_mrhof_parent_switch_threshold(const rpl_domain_t *domain); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index 2cef3653abb4..f2ec51204345 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -264,6 +264,10 @@ void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms) } +void rpl_control_set_parent_set_size(uint16_t parent_set_size) +{ +} + bool rpl_control_probe_parent_candidate(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) { return false; diff --git a/test/nanostack/unittest/stub/rpl_policy_stub.c b/test/nanostack/unittest/stub/rpl_policy_stub.c index f2aa60875295..f11bd5b3d3e8 100644 --- a/test/nanostack/unittest/stub/rpl_policy_stub.c +++ b/test/nanostack/unittest/stub/rpl_policy_stub.c @@ -158,6 +158,10 @@ uint_fast8_t rpl_policy_of0_max_backup_successors(const rpl_domain_t *domain) return 0; } +void rpl_policy_set_mrhof_parent_set_size(uint8_t parent_set_size) +{ +} + uint_fast8_t rpl_policy_mrhof_parent_set_size(const rpl_domain_t *domain) { return 0; From d65fcc6bf279919f4e4d9bb8dd8b6094fd9566ba Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 4 Feb 2020 15:19:06 +0200 Subject: [PATCH 65/88] Fix Wi-SUN network name comparison (#2294) Wi-SUN network name comparison function accepts partially matching network names. Adjust comparison so that network names must fully match. --- source/6LoWPAN/ws/ws_bootstrap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 9122eba73346..27840a6658ce 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -822,19 +822,26 @@ void ws_bootstrap_configuration_reset(protocol_interface_info_entry_t *cur) static bool ws_bootstrap_network_name_matches(const struct mcps_data_ie_list *ie_ext, const char *network_name_ptr) { + ws_wp_network_name_t network_name; + if (!network_name_ptr || !ie_ext) { return false; } - ws_wp_network_name_t network_name; if (!ws_wp_nested_network_name_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &network_name)) { tr_warn("No network name IE"); return false; } - if (network_name_ptr == NULL || strncmp(network_name_ptr, (char *)network_name.network_name, network_name.network_name_length) != 0) { + if (network_name.network_name_length != strlen(network_name_ptr)) { return false; } + + if (strncmp(network_name_ptr, (char *)network_name.network_name, network_name.network_name_length) != 0) { + return false; + } + + // names have equal length and same characters return true; } From 9b941af4b58682eb27ece650460c4e96ab5cd1bc Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Tue, 4 Feb 2020 16:01:43 +0200 Subject: [PATCH 66/88] Use default UC channel function in discovery, fixed BC schedule (#2284) --- source/6LoWPAN/ws/ws_bootstrap.c | 2 +- source/Service_Libs/fhss/fhss_ws.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 27840a6658ce..6cbb7f35e6cb 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -516,7 +516,7 @@ static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur) memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); } - fhss_configuration.ws_uc_channel_function = WS_FIXED_CHANNEL; + fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL; fhss_configuration.fhss_broadcast_interval = 0; uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index ab7e66016480..018bc062c8f5 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -229,8 +229,8 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure) fhss_structure->ws->bc_slot = 0; } } else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_DH1CF) { - next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels); fhss_structure->ws->bc_slot++; + next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels); } else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_VENDOR_DEF_CF) { if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) { next_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, NULL, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels); From aeb93a16ae0d9d627062a4c536f484dd7733ac99 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Tue, 4 Feb 2020 14:36:51 +0200 Subject: [PATCH 67/88] Add support for bbr configuration that removes default route from DIO New api bit added to configuration that removes the default route from DIO --- nanostack/ws_bbr_api.h | 12 ++++-------- source/6LoWPAN/ws/ws_bbr_api.c | 4 +++- source/6LoWPAN/ws/ws_bootstrap.c | 1 + source/RPL/rpl_control.c | 6 +++++- source/RPL/rpl_control.h | 4 ++++ source/RPL/rpl_upward.c | 15 ++++++++++++++- test/nanostack/unittest/stub/rpl_control_stub.c | 5 +++++ 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index a4d4d460e8fe..1559f433d55b 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -48,14 +48,10 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id); /** * Border router configuration options */ -#define BBR_ULA_C 0x0001 /**< Static ULA prefix created automatically */ -#define BBR_GUA_ROUTE 0x0002 /**< More specific route is added for GUA prefix */ -#define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */ - -/*Deprecated configuration values */ -#define BBR_GUA_C 0x0000 /**< Routable prefix is learned from the backbone */ -#define BBR_GUA_SLAAC 0x0000 /**< Use SLAAC addressing in routable prefix */ -#define BBR_GUA_WAIT 0x0000 /**< Wait backbone availability before startingRPL dodag */ +#define BBR_ULA_C 0x0001 /**< Static ULA prefix created automatically */ +#define BBR_GUA_ROUTE 0x0002 /**< More specific route is added for GUA prefix */ +#define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */ +#define BBR_DEFAULT_ROUTE 0x0008 /**< Add default route parameter to DIO */ /** * Configure border router features. diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index b9d0e153e7d3..858aaa022f27 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -423,7 +423,9 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) /* * Add default route to RPL */ - rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, WS_ROUTE_LIFETIME, false); + if (configuration & BBR_DEFAULT_ROUTE) { + rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, WS_ROUTE_LIFETIME, false); + } /* * Create static ULA configuration or modify if needed diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 6cbb7f35e6cb..c74a27fbb277 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2257,6 +2257,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback, cur); // If i am router I Do this rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); + rpl_control_process_routes(protocol_6lowpan_rpl_domain, false); // Wi-SUN assumes that no default route needed rpl_control_request_parent_link_confirmation(true); rpl_control_set_dio_multicast_min_config_advertisment_count(WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT); rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES); diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 635d80547d07..ab50eeed82d2 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -417,6 +417,7 @@ rpl_domain_t *rpl_control_create_domain(void) domain->callback = NULL; domain->cb_handle = NULL; domain->force_leaf = false; + domain->process_routes = true; ns_list_add_to_start(&rpl_domains, domain); addr_notification_register(rpl_control_addr_notifier); @@ -672,6 +673,10 @@ void rpl_control_force_leaf(rpl_domain_t *domain, bool leaf) } } } +void rpl_control_process_routes(rpl_domain_t *domain, bool process_routes) +{ + domain->process_routes = process_routes; +} /* Check whether the options section of a RPL control message is well-formed */ static bool rpl_control_options_well_formed(const uint8_t *dptr, uint_fast16_t dlen) @@ -941,7 +946,6 @@ static void rpl_control_process_route_options(rpl_instance_t *instance, rpl_doda } rpl_dodag_update_dio_route(dodag, prefix, prefix_len, flags, lifetime, true); } - /* We do not purge unadvertised routes. Thus if the root wants to purge * a route before its lifetime is up, stopping advertising it is not * sufficient, it has to advertise it with low or zero lifetime. This fits diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 4674eb76a3b9..464e5c2a8329 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -55,6 +55,8 @@ typedef struct rpl_domain { int8_t non_storing_downstream_interface; /* As part of shutdown, we can force entering leaf mode */ bool force_leaf; + /* if false routes are not set to routing table, instead default route is added for DODAGID */ + bool process_routes; rpl_domain_callback_t *callback; rpl_prefix_callback_t *prefix_cb; rpl_new_parent_callback_t *new_parent_add; @@ -137,6 +139,8 @@ void rpl_control_increment_dtsn(struct rpl_dodag *dodag); /* Force leaf behaviour on a domain - useful before shutdown, and in conjunction with poison */ void rpl_control_force_leaf(rpl_domain_t *domain, bool leaf); +/*Process routes from DIOs and add those as real routes. if routes are not processed assume DODAGID as default route*/ +void rpl_control_process_routes(rpl_domain_t *domain, bool process_routes); /* Manually send poison on all existing instances a few times */ void rpl_control_poison(rpl_domain_t *domain, uint8_t poison_count); diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index dae9ca5da095..3a3f95e94c5b 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1364,6 +1364,10 @@ void rpl_dodag_update_implicit_system_routes(rpl_dodag_t *dodag, rpl_neighbour_t /* Also add a specific route to the DODAGID */ ipv6_route_add_metric(dodag->id, 128, parent->interface_id, parent->ll_address, ROUTE_RPL_ROOT, parent, dodag->instance->id, default_lifetime, metric); + /* Check if we assume default route to DODAGID */ + if (!dodag->instance->domain->process_routes) { + ipv6_route_add_metric(NULL, 0, parent->interface_id, parent->ll_address, ROUTE_RPL_ROOT, parent, dodag->instance->id, default_lifetime, metric); + } } /* Called when a DIO RIO route has been updated (but not the parent list) */ @@ -1372,9 +1376,13 @@ static void rpl_dodag_update_system_route(rpl_dodag_t *dodag, rpl_dio_route_t *r if (!rpl_dodag_is_current(dodag)) { return; } - rpl_instance_t *instance = dodag->instance; + if (!instance->domain->process_routes) { + // We dont add actual routes and only create default route throuh DODAGID + return; + } + ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { if (neighbour->dodag_parent) { rpl_instance_update_system_dio_route(instance, neighbour, route); @@ -1389,6 +1397,11 @@ static void rpl_instance_update_system_routes_through_parent(rpl_instance_t *ins rpl_dodag_update_implicit_system_routes(dodag, parent); + if (!instance->domain->process_routes) { + // We dont add actual routes and only create default route through DODAGID + return; + } + /* Then add the specific routes listed in the DIO as ROUTE_RPL_DIO */ ns_list_foreach(rpl_dio_route_t, route, &dodag->routes) { rpl_instance_update_system_dio_route(instance, parent, route); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index f2ec51204345..9ef9f426589f 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -164,6 +164,11 @@ void rpl_control_force_leaf(rpl_domain_t *domain, bool leaf) } +void rpl_control_process_routes(rpl_domain_t *domain, bool process_routes) +{ + +} + void rpl_control_transmit(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, uint8_t code, struct buffer *buf, const uint8_t *dst) { From d40b1c7d0174bad98f7e685bb7336f878675ca06 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 5 Feb 2020 11:29:56 +0200 Subject: [PATCH 68/88] MAC: Updated calling FHSS TX done (#2295) --- source/MAC/IEEE802_15_4/mac_pd_sap.c | 44 +++++++++++++++++++--------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index b937f654b970..dc6b91e5c873 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -481,10 +481,6 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r return 0; } - // - bool waiting_ack = false; - - if (rf_ptr->mac_ack_tx_active) { mac_data_ack_tx_finish(rf_ptr); return 0; @@ -506,11 +502,40 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r timer_mac_stop(rf_ptr); } + if (rf_ptr->fhss_api && rf_ptr->active_pd_data_request->asynch_request == false) { + /* waiting_ack == false allows FHSS to change back to RX channel after transmission + * tx_completed == true allows FHSS to delete stored failure handles + */ + bool waiting_ack = false, tx_completed = false; + if (status == PHY_LINK_TX_SUCCESS && !rf_ptr->macTxRequestAck) { + waiting_ack = false; + tx_completed = true; + } else if (status == PHY_LINK_TX_SUCCESS && rf_ptr->macTxRequestAck) { + waiting_ack = true; + tx_completed = false; + } else if (status == PHY_LINK_CCA_FAIL) { + waiting_ack = false; + tx_completed = false; + } else if (status == PHY_LINK_CCA_OK) { + waiting_ack = false; + tx_completed = false; + } else if (status == PHY_LINK_TX_FAIL) { + waiting_ack = false; + tx_completed = false; + } else if (status == PHY_LINK_TX_DONE) { + waiting_ack = false; + tx_completed = true; + } else if (status == PHY_LINK_TX_DONE_PENDING) { + waiting_ack = false; + tx_completed = true; + } + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, waiting_ack, tx_completed, rf_ptr->active_pd_data_request->msduHandle); + } + switch (status) { case PHY_LINK_TX_SUCCESS: if (rf_ptr->macTxRequestAck) { timer_mac_start(rf_ptr, MAC_TIMER_ACK, rf_ptr->mac_ack_wait_duration); /*wait for ACK 1 ms*/ - waiting_ack = true; } else { //TODO CHECK this is MAC_TX_ PERMIT OK mac_tx_done_state_set(rf_ptr, MAC_TX_DONE); @@ -540,15 +565,6 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r default: break; } - if (rf_ptr->fhss_api) { - bool tx_is_done = false; - if (rf_ptr->mac_tx_result == MAC_TX_DONE) { - tx_is_done = true; - } - if (rf_ptr->active_pd_data_request->asynch_request == false) { - rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, waiting_ack, tx_is_done, rf_ptr->active_pd_data_request->msduHandle); - } - } return 0; } From 5b3055904a978ba134a37e77a6d9945a6bc3469e Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 6 Feb 2020 11:30:17 +0200 Subject: [PATCH 69/88] Allow unicast TX to overlap with MC (#2298) Allow unicast TX overlap with the next MC slot to improve data rate. Co-authored-by: Jarkko Paso --- source/Service_Libs/fhss/fhss_ws.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 018bc062c8f5..d5272250f833 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -606,6 +606,10 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure) static bool fhss_ws_check_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length) { + /* + * Check if there is enough time for transmitting before the next multicast slot. + */ +#ifdef FHSS_WS_PROTECT_MC_SLOTS if (!fhss_structure->ws->fhss_configuration.fhss_broadcast_interval || !fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) { return true; } @@ -615,6 +619,13 @@ static bool fhss_ws_check_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_ return false; } return true; +#else + (void) fhss_structure; + (void) tx_length; + (void) phy_header_length; + (void) phy_tail_length; + return true; +#endif } static bool fhss_ws_check_tx_conditions_callback(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) From 34d0339a4d8dc76bf7910dc142188b2881548100 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Thu, 6 Feb 2020 14:07:47 +0200 Subject: [PATCH 70/88] Wi-sun address registartion update ARO registartion will return new status if bootsrtap is not ready. Only Cache full status remove neighbour. Change-Id: I52fe7c21fd77f5f5ee208f2e976d227ba2f645f6 --- source/6LoWPAN/ND/nd_router_object.c | 12 +++++++----- source/6LoWPAN/ws/ws_common.c | 12 +++++++----- source/6LoWPAN/ws/ws_common.h | 4 ++-- source/Common_Protocols/icmpv6.c | 2 +- source/Common_Protocols/icmpv6.h | 1 + test/nanostack/unittest/stub/ws_common_stub.c | 4 ++-- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index 00beb5039f5d..53ff5ac59f16 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -928,11 +928,13 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin } /* TODO - check hard upper limit on registrations? */ - if (ws_info(cur_interface) && - !ws_common_allow_child_registration(cur_interface, aro_out->eui64)) { - aro_out->present = true; - aro_out->status = ARO_FULL; - return true; + if (ws_info(cur_interface)) { + + aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64); + if (aro_out->status != ARO_SUCCESS) { + aro_out->present = true; + return true; + } } /* We need to have entry in the Neighbour Cache */ diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 74a8dd18eed0..f89fbaa7483c 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -22,6 +22,7 @@ #include "randLIB.h" #include #include +#include "Common_Protocols/icmpv6.h" #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_common.h" @@ -405,7 +406,7 @@ void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8 -bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) { uint8_t child_count = 0; uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT; @@ -418,13 +419,13 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa //Validate Is EUI64 already allocated for any address if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) { tr_info("Child registration from old child"); - return true; + return ARO_SUCCESS; } //Verify that we have Selected Parent if (interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && !rpl_control_parent_candidate_list_size(interface, true)) { tr_info("Do not accept new ARO child: no selected parent"); - return false; + return ARO_TOPOLOGICALLY_INCORRECT; } @@ -436,10 +437,10 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa } if (child_count >= max_child_count) { tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); - return false; + return ARO_FULL; } tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); - return true; + return ARO_SUCCESS; } bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64) @@ -448,6 +449,7 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con if (!neighbour) { return false; } + ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index); ws_neighbor->negative_aro_send = true; neighbour->lifetime = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; //Remove anyway if Packet is freed before MAC push diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index aa977417ddd1..588902753ffc 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -141,7 +141,7 @@ void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t * void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); -bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64); +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64); bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64); @@ -158,7 +158,7 @@ uint32_t ws_common_version_timeout_get(uint8_t config); #define ws_common_aro_failure(cur, ll_address) #define ws_common_neighbor_remove(cur, ll_address) #define ws_common_fast_timer(cur, ticks) ((void) 0) -#define ws_common_allow_child_registration(cur, eui64) (false) +#define ws_common_allow_child_registration(cur, eui64) (2) #define ws_common_negative_aro_mark(interface, eui64)(false) #endif //HAVE_WS diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 32bcd71e1033..f0b3dc59eab2 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -1697,7 +1697,7 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited, memcpy(ptr, aro->eui64, 8); ptr += 8; } - if (ws_info(cur) && aro && aro->status != ARO_SUCCESS) { + if (ws_info(cur) && aro && (aro->status != ARO_SUCCESS && aro->status != ARO_TOPOLOGICALLY_INCORRECT)) { /*If Aro failed we will kill the neigbour after we have succeeded in sending message*/ if (!ws_common_negative_aro_mark(cur, aro->eui64)) { tr_debug("Neighbour removed for negative response send"); diff --git a/source/Common_Protocols/icmpv6.h b/source/Common_Protocols/icmpv6.h index c209e2af427c..3ae2aa14edf3 100644 --- a/source/Common_Protocols/icmpv6.h +++ b/source/Common_Protocols/icmpv6.h @@ -117,6 +117,7 @@ typedef enum slaac_src { #define ARO_SUCCESS 0 #define ARO_DUPLICATE 1 #define ARO_FULL 2 +#define ARO_TOPOLOGICALLY_INCORRECT 8 extern void icmpv6_init(void); extern struct buffer *icmpv6_down(struct buffer *buf); diff --git a/test/nanostack/unittest/stub/ws_common_stub.c b/test/nanostack/unittest/stub/ws_common_stub.c index 2e145f2bc98d..b7e1fb19be3b 100644 --- a/test/nanostack/unittest/stub/ws_common_stub.c +++ b/test/nanostack/unittest/stub/ws_common_stub.c @@ -62,10 +62,10 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8 (void) cur; (void) ll_address; } -bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) { (void) interface; - return true; + return 0; } void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) { From b9187daa624eaeca226f3c2f62c9f61433395c82 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Thu, 6 Feb 2020 15:39:18 +0200 Subject: [PATCH 71/88] Randomize fixed channel when making new parent selection --- source/6LoWPAN/ws/ws_bootstrap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index c74a27fbb277..2f7146795854 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2807,6 +2807,10 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur); if (!selected_parent_ptr) { + // Configure LLC for network discovery + ws_bootstrap_network_discovery_configure(cur); + // randomize new channel and start MAC + ws_bootstrap_fhss_activate(cur); // Next check will be after one trickle cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50; tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); @@ -2825,9 +2829,6 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) //Remove Neighbour and set Link setup back ns_list_remove(&cur->ws_info->parent_list_reserved, selected_parent_ptr); ns_list_add_to_end(&cur->ws_info->parent_list_free, selected_parent_ptr); - // Configure LLC for network discovery - ws_bootstrap_network_discovery_configure(cur); - ws_bootstrap_fhss_activate(cur); goto select_best_candidate; } From 6cde17ad9c6c57b82eb7b113de1373b53817b02c Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Fri, 7 Feb 2020 11:05:24 +0200 Subject: [PATCH 72/88] Iotthd 3963 2 (#2301) * WS bootstrap: Use UC fixed channel in discovery, configured in EAPOL * Single function for ws fhss configure --- source/6LoWPAN/ws/ws_bootstrap.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 2f7146795854..b07d36191e51 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -506,7 +506,7 @@ static uint16_t ws_randomize_fixed_channel(uint16_t configured_fixed_channel, ui } } -static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur) +static int8_t ws_fhss_configure(protocol_interface_info_entry_t *cur, bool discovery) { // Read configuration of existing FHSS and start using the default values for any network fhss_ws_configuration_t fhss_configuration; @@ -515,8 +515,12 @@ static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur) if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) { memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); } - - fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; + // Discovery is done using fixed channel + if (discovery) { + fhss_configuration.ws_uc_channel_function = WS_FIXED_CHANNEL; + } else { + fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; + } fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL; fhss_configuration.fhss_broadcast_interval = 0; uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); @@ -2280,7 +2284,7 @@ static void ws_bootstrap_network_discovery_configure(protocol_interface_info_ent cur->ws_info->network_pan_id = 0xffff; ws_common_regulatory_domain_config(cur); - ws_fhss_discovery_configure(cur); + ws_fhss_configure(cur, true); //Set Network names, Pan information configure, hopping schedule & GTKHash ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->network_name, strlen(cur->ws_info->network_name)); @@ -2937,7 +2941,7 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; - + ws_fhss_configure(cur, false); ws_bootstrap_start_authentication(cur); break; case ER_RPL_SCAN: From 1acec7cdcc603a37fd1c437b2bd3a0f043b2fa31 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 29 Jan 2020 15:56:03 +0200 Subject: [PATCH 73/88] Aro Registation and Dao update Aro registration stop Active DAO process. DAO transit build set fully path controller bit's. Change-Id: Id692dc51611aa3a4c4df6668d0a4bfc11e454f67 --- source/RPL/rpl_downward.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 9cc7d7912307..6f7a5dbfcb5a 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -545,8 +545,7 @@ static rpl_dao_target_t *rpl_instance_choose_target_to_assign(rpl_instance_t *in */ ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { if (neighbour->dao_path_control & unassigned_pc) { - unassigned_pc &= neighbour->dao_path_control; - *path_control = unassigned_pc; + *path_control = neighbour->dao_path_control; *parent = neighbour; return target; } @@ -561,14 +560,7 @@ static rpl_dao_target_t *rpl_instance_choose_target_to_assign(rpl_instance_t *in } } - /* If looking for a follow-up target, final path control must match */ - if (t1) { - if (unassigned_pc != *path_control) { - continue; - } - } else { - *path_control = unassigned_pc; - } + *path_control = target->path_control; return target; } @@ -1811,6 +1803,8 @@ static void rpl_instance_address_registration_cancel(rpl_instance_t *instance) instance->wait_response = NULL; instance->pending_neighbour_confirmation = false; instance->delay_dao_timer = 0; + instance->dao_in_transit = false; + instance->dao_retry_timer = 0; } void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint16_t seconds) From 6283dfd6432174b6cd3272811bfa3e4a370149b7 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Fri, 7 Feb 2020 12:26:35 +0200 Subject: [PATCH 74/88] DIO advertisment fix Wi-sun bootsratap rules was broke DIO advertisment aat error case when RANK start goes worster. Change-Id: I776882bc5d5da7bb223825ed6a9236cfe7be9799 --- source/RPL/rpl_upward.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 3a3f95e94c5b..99377e6150c7 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1833,17 +1833,21 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) if (rpl_dodag_am_leaf(dodag) && !instance->poison_count) { return; } - // We dont have any valid address in interface - if (ns_list_count(&instance->dao_targets) == 0) { - return; - } - /* Address registrations for parent ongoing*/ - if (rpl_policy_parent_confirmation_requested() && instance->pending_neighbour_confirmation) { - return; - } - /* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */ - if (instance->dao_in_transit || instance->delay_dao_timer > 0) { - return; + /* Delay sending first DIO if we are still potentially gathering info */ + /* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */ + if (!instance->last_advertised_dodag_version && rpl_policy_parent_confirmation_requested()) { + // We dont have any valid address in interface + if (ns_list_count(&instance->dao_targets) == 0) { + return; + } + /* Address registrations for parent ongoing*/ + if (instance->pending_neighbour_confirmation) { + return; + } + /* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */ + if (instance->dao_in_transit || instance->delay_dao_timer > 0) { + return; + } } if (trickle_timer(&instance->dio_timer, &dodag->dio_timer_params, ticks)) { instance->dio_not_consistent = false; From 8bda17644546563ad4a2892c2bf132ac982c58e1 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Fri, 7 Feb 2020 14:54:37 +0200 Subject: [PATCH 75/88] Wi-sun boot fix Cleared generic bootstrap stame machine timer. Now we are not trig ER_ACTIVE_SCAN state to border router. Change-Id: I41113e4501cbf35b2d07285599212bad954a659c --- source/6LoWPAN/ws/ws_bootstrap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index b07d36191e51..0b46f17491b1 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -719,6 +719,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) goto cleanup; } + /* Wi-sun will trig event for stamechine this timer must be zero on init */ + cur->bootsrap_state_machine_cnt = 0; /* Disable SLLAO send/mandatory receive with the ARO */ cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true; /* Omit sending of NA if ARO SUCCESS */ From 4185734223be99d75ecd7845f772ad143231e825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Thu, 6 Feb 2020 20:25:41 +0200 Subject: [PATCH 76/88] Improved EAPOL key update retry logic EAPOL key update now checks after all retries have been done, whether GTKs are up to date (by comparing to latest GTK hash). If they are not, it initiates a new key update rigth away. Previously EAPOL waited for PAN version update before initiating the key update. Also added a check that if key update procedure is on the last interval (waiting for the authenticator to answer the last retry), and GTK hash changes, EAPOL key update is retried rigth away. --- source/6LoWPAN/ws/ws_pae_controller.c | 4 +-- source/6LoWPAN/ws/ws_pae_supp.c | 46 ++++++++++++++++++++++++--- source/6LoWPAN/ws/ws_pae_supp.h | 12 ++++++- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 4cb64cf9ea39..f5bc4dba9220 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -679,7 +679,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update; controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update; - ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set); + ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get); ws_pae_controller_frame_counter_read(controller); @@ -1203,7 +1203,7 @@ int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interf memcpy(controller->gtkhash, gtkhash, 32); if (controller->pae_gtk_hash_update) { - return controller->pae_gtk_hash_update(interface_ptr, gtkhash); + return controller->pae_gtk_hash_update(interface_ptr, controller->gtkhash); } return 0; diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index bde4539ce2f4..37d8bccb5347 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -91,6 +91,7 @@ typedef struct { ws_pae_supp_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */ ws_pae_supp_nw_key_insert *nw_key_insert; /**< Key insert callback */ ws_pae_supp_nw_key_index_set *nw_key_index_set; /**< Key index set callback */ + ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get; /**< Get pointer to GTK hash storage callback */ supp_entry_t entry; /**< Supplicant data */ kmp_addr_t target_addr; /**< EAPOL target (parent) address */ uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */ @@ -114,6 +115,10 @@ typedef struct { // How many times sending of initial EAPOL-key is retried #define INITIAL_KEY_RETRY_COUNT 2 +// How many times sending of initial EAPOL-key is initiated on key update +#define KEY_UPDATE_RETRY_COUNT 3 +#define LIFETIME_MISMATCH_RETRY_COUNT 1 /* No retries */ + // How long the wait is before the first initial EAPOL-key retry #define DEFAULT_INITIAL_KEY_RETRY_TIMER 120 #define NONE_INITIAL_KEY_RETRY_TIMER 0 @@ -163,6 +168,7 @@ static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp); static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64); static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64); +static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp); static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result); static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr); @@ -317,6 +323,23 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr) return 0; } +static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp) +{ + uint8_t *gtkhash = pae_supp->gtk_hash_ptr_get(pae_supp->interface_ptr); + if (!gtkhash) { + return -1; + } + + // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */ + gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(&pae_supp->gtks, gtkhash); + if (mismatch != GTK_NO_MISMATCH) { + return -1; + } + + tr_info("GTKs match to GTK hash"); + return 0; +} + int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash) { pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); @@ -333,12 +356,13 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt trace_array(>khash[16], 8), trace_array(>khash[24], 8)); - // Mismatch, initiate EAPOL - if (!pae_supp->auth_trickle_running) { - uint8_t timer_expirations = 3; + /* Mismatch, initiate EAPOL (if authentication not already ongoing or if not on + wait time for the authenticator to answer) */ + if (!pae_supp->auth_trickle_running || pae_supp->initial_key_retry_cnt == 0) { + uint8_t timer_expirations = KEY_UPDATE_RETRY_COUNT; // For GTK lifetime mismatch send only once if (mismatch == GTK_LIFETIME_MISMATCH) { - timer_expirations = 1; + timer_expirations = LIFETIME_MISMATCH_RETRY_COUNT; } // Start trickle timer ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, timer_expirations); @@ -581,7 +605,7 @@ static void ws_pae_supp_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_i sec_keys_nw_info->updated = false; } -void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set) +void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get) { pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); if (!pae_supp) { @@ -591,6 +615,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ pae_supp->auth_completed = completed; pae_supp->nw_key_insert = nw_key_insert; pae_supp->nw_key_index_set = nw_key_index_set; + pae_supp->gtk_hash_ptr_get = gtk_hash_ptr_get; } int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings) @@ -612,6 +637,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se pae_supp->auth_completed = NULL; pae_supp->nw_key_insert = NULL; pae_supp->nw_key_index_set = NULL; + pae_supp->gtk_hash_ptr_get = NULL; pae_supp->initial_key_timer = 0; pae_supp->initial_key_retry_timer = 0; pae_supp->nw_keys_used_cnt = 0; @@ -866,7 +892,17 @@ void ws_pae_supp_slow_timer(uint16_t seconds) /* Wait time for the authenticator to answer the last re-transmit expires; fails authentication */ if (pae_supp->initial_key_retry_cnt == 0) { + bool retry = false; + // If making key update and GTKs do not match to GTK hash + if (!pae_supp->auth_requested && ws_pae_supp_gtk_hash_mismatch_check(pae_supp) < 0) { + tr_info("GTKs do not match to GTK hash"); + retry = true; + } ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC); + if (retry) { + // Start trickle timer to try re-authentication + ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, KEY_UPDATE_RETRY_COUNT); + } } else { if (pae_supp->initial_key_retry_cnt > 0) { pae_supp->initial_key_retry_cnt--; diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index bc8fc0f0110d..458ed7bf9ea5 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -236,6 +236,16 @@ typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interfa */ typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); +/** + * ws_pae_supp_gtk_hash_ptr_get get pointer to GTK hash storage callback + * + * \param interface_ptr interface + * + * \return pointer to GTK has storage or NULL + * + */ +typedef uint8_t *ws_pae_supp_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr); + /** * ws_pae_supp_cb_register register PEA supplicant callbacks * @@ -245,7 +255,7 @@ typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interf * \param nw_key_index_set network send key index callback * */ -void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set); +void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get); #else From 7717ef8c606093ab999e4421b5f127d6c76c6044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Fri, 7 Feb 2020 02:00:53 +0200 Subject: [PATCH 77/88] Improved initial EAPOL-key send stop logic on supplicant Previously, during bootstrap authentication and on key update, any incoming KMP halted the supplicant from sending the initial EAPOL-key message to authenticator. Now the functionality is changed so that only accepted incoming KMPs (e.g. valid EAP-TLS identity requests) halt the sending of initial EAPOL-key messages. Ignored KMPs do not halt the sending. --- source/6LoWPAN/ws/ws_pae_supp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 37d8bccb5347..3799787e47b5 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -1175,9 +1175,6 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_ return NULL; } - // No longer runs trickle timer for re-sending initial EAPOL-key - pae_supp->auth_trickle_running = false; - // Updates parent address kmp_address_copy(&pae_supp->entry.addr, addr); @@ -1271,6 +1268,15 @@ static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ (void) addr; (void) type; + kmp_service_t *service = kmp_api_service_get(kmp); + pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service); + if (!pae_supp) { + return; + } + + // Incoming KMP protocol has started, no longer runs trickle timer for re-sending EAPOL-key message + pae_supp->auth_trickle_running = false; + // For now, accept every KMP-CREATE.indication kmp_api_create_response(kmp, KMP_RESULT_OK); } From 015f3fe60ebd1d1013f04430d25b23d9baafbf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Tue, 11 Feb 2020 22:33:36 +0200 Subject: [PATCH 78/88] Corrected bitfield definition --- source/Security/protocols/sec_prot_keys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index 15b8dbc32bab..9df422934b9b 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -89,7 +89,7 @@ typedef struct { uint32_t ptk_lifetime; /**< PTK lifetime in seconds */ uint8_t gtkl; /**< Remote GTKL information */ int8_t gtk_set_index; /**< Index of GTK to set */ - uint8_t ins_gtk_hash_set: 4; /**< Hash for inserted GTKs for a PTK set */ + unsigned ins_gtk_hash_set: 4; /**< Hash for inserted GTKs for a PTK set */ bool pmk_set: 1; /**< Pairwise Master Key set */ bool ptk_set: 1; /**< Pairwise Transient Key set */ bool pmk_key_replay_cnt_set: 1; /**< Pairwise Master Key replay counter set */ From 6b6f535828b1d5dedb46691859c800a5e74c6a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Wed, 12 Feb 2020 02:13:31 +0200 Subject: [PATCH 79/88] Corrected EUI-64 address bit flip on supplicant --- source/6LoWPAN/ws/ws_pae_supp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 3799787e47b5..db891dc6e4ac 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -1101,7 +1101,7 @@ static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *int const uint8_t *parent_ll_addr = rpl_control_preferred_parent_addr(instance, false); if (parent_ll_addr) { memcpy(eui_64, &parent_ll_addr[8], 8); - eui_64[0] |= 0x02; + eui_64[0] ^= 0x02; return 0; } } From f728d559205c9b09d1964694deb562733eec3d73 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 12 Feb 2020 18:26:29 +0200 Subject: [PATCH 80/88] Support for handle CRC error which will automatically change a channel. If Driver call data ind with zero length we can then handle that like CRC error which will change a FHHS channel if is pending. Change-Id: Iba0cdce8dabf20f1640e63b33c116d7d3c0a9254 --- source/MAC/IEEE802_15_4/mac_pd_sap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index dc6b91e5c873..1b8eda122918 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -890,6 +890,11 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) if (message->id == MAC15_4_PD_SAP_DATA_IND) { arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind); + mac_pre_parsed_frame_t *buffer = NULL; + if (pd_data_ind->data_len == 0) { + goto ERROR_HANDLER; + } + if (pd_data_ind->data_len < 3) { return -1; } @@ -897,7 +902,7 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) mac_fcf_sequence_t fcf_read; const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr); - mac_pre_parsed_frame_t *buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind); + buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind); if (buffer && mac_filter_modify_link_quality(rf_ptr->mac_interface_id, buffer) == 1) { goto ERROR_HANDLER; } @@ -935,7 +940,9 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) } ERROR_HANDLER: mcps_sap_pre_parsed_frame_buffer_free(buffer); - sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0); + if (pd_data_ind->data_len >= 3) { + sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0); + } if (rf_ptr->fhss_api) { rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0); } From 05aa54c464572013841b4cfb0a82bde45620feae Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Tue, 18 Feb 2020 11:24:36 +0200 Subject: [PATCH 81/88] Update MPL parameters to follow Specification IMAX should be 80 seconds by default --- source/6LoWPAN/ws/ws_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index b29fbddec1e6..5f2bcab57980 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -103,7 +103,7 @@ extern uint8_t DEVICE_MIN_SENS; #define DATA_MESSAGE_IMIN (10 * 1000) #define DATA_MESSAGE_TIMER_EXPIRATIONS 3 -#define DATA_MESSAGE_IMAX (DATA_MESSAGE_IMIN) +#define DATA_MESSAGE_IMAX (80 * 1000) #define MPL_SEED_SET_ENTRY_TIMEOUT (DATA_MESSAGE_IMAX * 24 * 4 / 1000) // 10 seconds per hop making this 240 seconds /* DHCP client timeout configuration values From c8560dbe01aec715a7e5a7c12386bcaf43bf1c18 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 19 Feb 2020 09:53:32 +0200 Subject: [PATCH 82/88] Updated RPL default memory sof and hard limit to 2/4 from 1/2. This is mandatory change to support store 16 version update. Change-Id: Id7111a323580bafc34693f9b52ce455feb83517b --- source/RPL/rpl_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index ab50eeed82d2..b17dce381e91 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -60,8 +60,8 @@ const uint8_t ADDR_LINK_LOCAL_ALL_RPL_NODES[16] = { 0xff, 0x02, [15] = 0x1a }; /* Sensible default limits for a 6LoWPAN-ND node */ -static size_t rpl_purge_threshold = 1 * 1024; -static size_t rpl_alloc_limit = 2 * 1024; // 0 means no limit +static size_t rpl_purge_threshold = 2 * 1024; +static size_t rpl_alloc_limit = 4 * 1024; // 0 means no limit static size_t rpl_alloc_total; #define RPL_ALLOC_OVERHEAD 8 From 18247d546f098cf1934c8965d9fe28017d510e52 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 19 Feb 2020 10:27:58 +0200 Subject: [PATCH 83/88] Wi-sun RPL memory soft and hard limit update Set more RAM for for Wi-sun RPL router from 2/4 to 3/6 Change-Id: I0ecf8ccef192b48acc534677608016d92985614a --- source/6LoWPAN/ws/ws_bootstrap.c | 3 +++ source/6LoWPAN/ws/ws_config.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 0b46f17491b1..a400eb09d3e5 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -2269,6 +2269,9 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES); rpl_control_set_initial_dao_ack_wait(WS_MAX_DAO_INITIAL_TIMEOUT); rpl_control_set_mrhof_parent_set_size(WS_MAX_PARENT_SET_COUNT); + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + rpl_control_set_memory_limits(WS_NODE_RPL_SOFT_MEM_LIMIT, WS_NODE_RPL_HARD_MEM_LIMIT); + } cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event } diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 5f2bcab57980..e7afc90d9825 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -151,6 +151,9 @@ extern uint8_t DEVICE_MIN_SENS; #define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 0xff // Advertisment config at every MC DIO #define WS_MAX_PARENT_SET_COUNT 2 // maximum amount of parents selected by node +#define WS_NODE_RPL_SOFT_MEM_LIMIT 4*1024 // Limit when RPL start purge unused data +#define WS_NODE_RPL_HARD_MEM_LIMIT 6*1024 // Limit when RPL memory allocation start limit allocation + /* * Candidate parent list parameters */ From 9b82abff039def320cdb3a63216d784877541eb8 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 19 Feb 2020 13:43:52 +0200 Subject: [PATCH 84/88] =?UTF-8?q?Copy=20IE=20unicast=20channel=20function?= =?UTF-8?q?=20from=20WS=20info=20instead=20of=20FHSS=20configu=E2=80=A6=20?= =?UTF-8?q?(#2310)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Copy IE unicast channel function from WS info instead of FHSS configuration * Added comment --- source/6LoWPAN/ws/ws_bootstrap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index a400eb09d3e5..6aaffc1a8ece 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -412,7 +412,8 @@ static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry memcpy(cur->ws_info->hopping_schdule.channel_mask, fhss_configuration->channel_mask, sizeof(uint32_t) * 8); cur->ws_info->hopping_schdule.uc_fixed_channel = fhss_configuration->unicast_fixed_channel; cur->ws_info->hopping_schdule.bc_fixed_channel = fhss_configuration->broadcast_fixed_channel; - cur->ws_info->hopping_schdule.uc_channel_function = fhss_configuration->ws_uc_channel_function; + // Read UC channel function from WS info because FHSS might be temporarily configured to fixed channel during discovery. + cur->ws_info->hopping_schdule.uc_channel_function = cur->ws_info->fhss_uc_channel_function; cur->ws_info->hopping_schdule.bc_channel_function = fhss_configuration->ws_bc_channel_function; cur->ws_info->hopping_schdule.fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval; cur->ws_info->hopping_schdule.fhss_broadcast_interval = fhss_configuration->fhss_broadcast_interval; From 63e4680ca3b92138609ab1a04a532496e9a2e21e Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 19 Feb 2020 15:01:50 +0200 Subject: [PATCH 85/88] Allow buffer_dyn to handle more data (#2311) Buffer fails to handle more than INT16_MAX bytes of data. To fix the problem: -Modify buffer checks to allow handling of 65532 (0xFFFC) bytes of data (as we have 16-bit counters). -Deny allocation of buffer that have more than 0xFFFF bytes of data. --- source/Core/buffer_dyn.c | 43 ++++-- source/Core/include/ns_buffer.h | 2 +- .../Core/buffer_dyn/buffer_dyntest.cpp | 4 + .../Core/buffer_dyn/test_buffer_dyn.c | 140 +++++++++++++++++- .../Core/buffer_dyn/test_buffer_dyn.h | 2 + 5 files changed, 172 insertions(+), 19 deletions(-) diff --git a/source/Core/buffer_dyn.c b/source/Core/buffer_dyn.c index 1b34e6499738..268ee815ab90 100644 --- a/source/Core/buffer_dyn.c +++ b/source/Core/buffer_dyn.c @@ -16,7 +16,8 @@ */ #include "nsconfig.h" -#include "string.h" +#include +#include #include "ns_types.h" #include "nsdynmemLIB.h" #include "Core/include/ns_address_internal.h" @@ -30,6 +31,13 @@ #define TRACE_GROUP "buff" +// Get module working also on 16-bit platform +#if INT_MAX < 0xFFFF +#define BUFFER_MAX_SIZE ((size_t)INT_MAX) +#else +#define BUFFER_MAX_SIZE ((size_t)0xFFFF) +#endif + volatile unsigned int buffer_count = 0; uint8_t *(buffer_corrupt_check)(buffer_t *buf) @@ -38,15 +46,12 @@ uint8_t *(buffer_corrupt_check)(buffer_t *buf) return NULL; } - if (buf->buf_ptr > buf->buf_end) { - tr_error("Buffer pointer end not set"); - } else if (buffer_data_length(buf) < 0) { - tr_error("Buffer length overflow"); - while (1); - } else if (buf->buf_end > buf->size || buf->buf_ptr > buf->size) { - tr_error("buffer pointer overridden"); + if (buf->buf_ptr > buf->buf_end || buf->buf_end > buf->size) { + tr_error("Invalid buffer, size=%"PRIu16", buf_ptr=%"PRIu16", buf_end=%"PRIu16"", buf->size, buf->buf_ptr, buf->buf_end); + tr_error("Data: %s", tr_array(buffer_data_pointer(buf), 56)); while (1); } + return buffer_data_pointer(buf); } @@ -71,8 +76,8 @@ buffer_t *buffer_get_minimal(uint16_t size) */ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspace) { - buffer_t *buf; - uint16_t total_size; + buffer_t *buf = NULL; + uint32_t total_size; total_size = headroom + size; if (total_size < minspace) { @@ -83,10 +88,12 @@ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspac * anyway be this much aligned. */ total_size = (total_size + 3) & ~ 3; - // Note - as well as this alloc+init, buffers can also be "realloced" - // in buffer_headroom() + if (total_size <= BUFFER_MAX_SIZE) { + // Note - as well as this alloc+init, buffers can also be "realloced" + // in buffer_headroom() + buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + total_size); + } - buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + total_size); if (buf) { platform_enter_critical(); buffer_count++; @@ -110,7 +117,7 @@ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspac #endif buf->size = total_size; } else { - tr_error("buffer_get failed: alloc(%d)", (int) sizeof(buffer_t) + total_size); + tr_error("buffer_get failed: alloc(%"PRIu32")", (uint32_t)(sizeof(buffer_t) + total_size)); } protocol_stats_update(STATS_BUFFER_ALLOC, 1); @@ -130,10 +137,14 @@ buffer_t *buffer_headroom(buffer_t *buf, uint16_t size) uint16_t curr_len = buffer_data_length(buf); if (buf->size < (curr_len + size)) { + buffer_t *restrict new_buf = NULL; /* This buffer isn't big enough at all - allocate a new block */ // TODO - should we be giving them extra? probably - uint16_t new_total = (curr_len + size + 3) & ~ 3; - buffer_t *restrict new_buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + new_total); + uint32_t new_total = (curr_len + size + 3) & ~ 3; + if (new_total <= BUFFER_MAX_SIZE) { + new_buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + new_total); + } + if (new_buf) { // Copy the buffer_t header *new_buf = *buf; diff --git a/source/Core/include/ns_buffer.h b/source/Core/include/ns_buffer.h index 7ebb6e05454a..b33148a14d18 100644 --- a/source/Core/include/ns_buffer.h +++ b/source/Core/include/ns_buffer.h @@ -322,7 +322,7 @@ struct socket *buffer_socket_set(buffer_t *buf, struct socket *socket); } while(0) /** get data length*/ -#define buffer_data_length(x) (int16_t)(x->buf_end - x->buf_ptr) +#define buffer_data_length(x) (int)(x->buf_end - x->buf_ptr) /** get data length Set*/ #define buffer_data_length_set(x,z) ((x)->buf_end = (x)->buf_ptr + (z)) diff --git a/test/nanostack/unittest/Core/buffer_dyn/buffer_dyntest.cpp b/test/nanostack/unittest/Core/buffer_dyn/buffer_dyntest.cpp index 4e47bd855615..be6c0d2a358f 100644 --- a/test/nanostack/unittest/Core/buffer_dyn/buffer_dyntest.cpp +++ b/test/nanostack/unittest/Core/buffer_dyn/buffer_dyntest.cpp @@ -31,3 +31,7 @@ TEST(buffer_dyn, test_buffer_get) CHECK(test_buffer_get()); } +TEST(buffer_dyn, test_buffer_get_minimal) +{ + CHECK(test_buffer_get_minimal()); +} diff --git a/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.c b/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.c index 5f65ff007e88..c6e1ea987719 100644 --- a/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.c +++ b/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.c @@ -14,15 +14,151 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "test_buffer_dyn.h" + +#include "nsconfig.h" #include +#include "ns_types.h" +#include "ns_buffer.h" +#include "test_buffer_dyn.h" +#include "nsdynmemLIB_stub.h" +#define FILL_MARK 0x05 +bool test_buffer_get_and_data_add(uint16_t size, bool use_minimal); + + +bool test_buffer_get_minimal_with_size(uint16_t size) +{ + return test_buffer_get_and_data_add(size, true); +} + +bool test_buffer_get_with_size(uint16_t size) +{ + return test_buffer_get_and_data_add(size, false); +} + +bool test_buffer_get_and_data_add(uint16_t size, bool use_minimal) +{ + buffer_t *buf; + uint8_t *data_ptr; + uint16_t data_len; + + nsdynmemlib_stub.returnCounter = 1; + + data_len = size; + + if (use_minimal) { + buf = buffer_get_minimal(data_len); + } else { + buf = buffer_get(data_len); + } + if (!buf) { + return false; + } + + // Add data to buffer + data_ptr = malloc(data_len); + memset(data_ptr, FILL_MARK, data_len); + buffer_data_add(buf, data_ptr, data_len); + + // validate content + if (memcmp(buffer_data_pointer(buf), data_ptr, data_len) != 0) { + return false; + } + + // validate buffer length + if (buffer_data_length(buf) != data_len) { + return false; + } + + buffer_free(buf); + free(data_ptr); + + return true; +} bool test_buffer_get() { - if (buffer_get(1)) { + buffer_t *buf; + uint8_t *data_ptr; + uint16_t data_len; + + // memory allocation failure + buf = buffer_get(1); + if (buf) { + return false; + } + + // Test with (0xffff - BUFFER_DEFAULT_HEADROOM) aligned) + uint16_t len = (0xffff - BUFFER_DEFAULT_HEADROOM - 4) + 3 & ~ 3; + if (test_buffer_get_with_size(len) == false) { return false; } + + len = len + 1; + if (test_buffer_get_with_size(len) == true) { + return false; + } + + // Test with 32767 + if (test_buffer_get_with_size(0x7fff) == false) { + return false; + } + + // Test with 32768 + if (test_buffer_get_with_size(0x7fff + 1) == false) { + return false; + } + + // test with 0-256 + for (int i = 0; i <= 256; i++) { + if (test_buffer_get_with_size(i) == false) { + return false; + } + } + return true; } +bool test_buffer_get_minimal() +{ + buffer_t *buf; + uint8_t *data_ptr; + uint16_t data_len; + + // memory allocation failure + buf = buffer_get_minimal(1); + if (buf) { + return false; + } + + // Test with (0xffff - 4) aligned) + uint16_t len = (0xffff - 4) + 3 & ~ 3; + if (test_buffer_get_minimal_with_size(len) == false) { + return false; + } + + // Test with too long size, fails + len = len + 1; + if (test_buffer_get_minimal_with_size(len) == true) { + return false; + } + + // Test with 32767 + if (test_buffer_get_minimal_with_size(0x7fff) == false) { + return false; + } + + // Test with 32768 + if (test_buffer_get_minimal_with_size(0x7fff + 1) == false) { + return false; + } + + // test with 0-256 + for (int i = 0; i <= 256; i++) { + if (test_buffer_get_minimal_with_size(i) == false) { + return false; + } + } + + return true; +} diff --git a/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.h b/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.h index cb07159be9da..b21cc1914c5d 100644 --- a/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.h +++ b/test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.h @@ -25,6 +25,8 @@ extern "C" { bool test_buffer_get(); +bool test_buffer_get_minimal(); + #ifdef __cplusplus } #endif From 2bd05584fe0bb9c5615aea3d1a2797fcaa3e6250 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Wed, 19 Feb 2020 11:42:24 +0200 Subject: [PATCH 86/88] Wi-sun border router DHCPv6 server address alocation update Changed default value 200 which is limiting big network testing to new MAX_SUPPORTED_ADDRESS_LIST_SIZE. Change-Id: I25c7a5f1c82422cb1ea1a1e70dec89df3edd48ff --- source/6LoWPAN/ws/ws_bbr_api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 858aaa022f27..7961f10cc951 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -343,6 +343,8 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8 //Enable SLAAC mode to border router DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME); + //SEt max value for not limiting address allocation + DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE); ws_dhcp_client_address_request(cur, global_id, ll); } From c906c43a8a3eadef468829dca463cd3f7c033600 Mon Sep 17 00:00:00 2001 From: David Lin Date: Sun, 16 Feb 2020 18:31:22 +0800 Subject: [PATCH 87/88] Fixed typo: 'lenght' in ns_crc.h Note that the word 'lenght' is wrong, so that 'lenght' should been replaced with 'length'. --- source/Service_Libs/utils/ns_crc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Service_Libs/utils/ns_crc.h b/source/Service_Libs/utils/ns_crc.h index f229b97e67ef..92fad32272f2 100644 --- a/source/Service_Libs/utils/ns_crc.h +++ b/source/Service_Libs/utils/ns_crc.h @@ -31,7 +31,7 @@ uint16_t crc16_ccitt(uint8_t *message, int nBytes); /** * @param data data which crc will be calculate - * @param data_length Lenght of data pointer + * @param data_length Length of data pointer * @param polynomial Polynomial which will be used to calculate CRC, POLYNOMIAL_CRC15_CCIT, POLYNOMIAL_CRC15_ANSI * @return Calculated 16bit CRC value */ From c536960fb0ebccec2d7410f684a471cbb1e33b42 Mon Sep 17 00:00:00 2001 From: Juha Heiskanen Date: Tue, 3 Dec 2019 13:30:58 +0200 Subject: [PATCH 88/88] DHCPv6 Server feature update Wi-sun border router disable dhcpv6 non autonoumous mode. Added possibility for skip alloacted address storing. Optimized Allocated address entry RAM usage 14 bytes. Server will now support 16-bit address id allocaing and it 64-bit suffics is genated by adding 48-bit padding which is genertaed from server unique link ID + 16-bit allocated id. Change-Id: I958a655a96fefd14ce75315b7149d8800ca7e9f8 --- source/6LoWPAN/Thread/thread_management_if.c | 2 +- source/6LoWPAN/ws/ws_bbr_api.c | 2 +- source/DHCPv6_Server/DHCPv6_Server_service.c | 67 ++-- source/DHCPv6_Server/DHCPv6_server_service.h | 3 +- source/libDHCPv6/libDHCPv6_server.c | 329 ++++++++++++++---- source/libDHCPv6/libDHCPv6_server.h | 49 ++- .../stub/dhcpv6_server_service_stub.c | 2 +- .../unittest/stub/libDHCPv6_server_stub.c | 11 +- 8 files changed, 343 insertions(+), 122 deletions(-) diff --git a/source/6LoWPAN/Thread/thread_management_if.c b/source/6LoWPAN/Thread/thread_management_if.c index 435ab5133458..7409f53a9078 100644 --- a/source/6LoWPAN/Thread/thread_management_if.c +++ b/source/6LoWPAN/Thread/thread_management_if.c @@ -699,7 +699,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t * return -1; } - return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous); + return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous, false); #else (void) interface_id; (void) prefix_ptr; diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 390de439329d..54d5133d2971 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -308,7 +308,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8 } DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb); - DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true); + DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, false, false); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME); ws_dhcp_client_address_request(cur, global_id, ll); diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index c2f567e40f76..a7755034a9df 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -87,7 +87,7 @@ static void DHCP_server_service_timer_stop(void) int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_reply_packet_s *replyPacket, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, dhcpv6_gua_response_t *response, bool allocateNew) { - dhcpv6_alloacted_address_entry_t *dhcp_allocated_address = NULL; + dhcpv6_allocated_address_t *dhcp_allocated_address = NULL; dhcpv6_ia_non_temporal_address_s nonTemporalAddress; bool address_allocated = false; //Validate Client DUID @@ -279,12 +279,15 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], { dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); if (serverInfo) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { //Delete Server data base if (serverInfo->removeCb) { - serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL); + uint8_t allocated_address[16]; + libdhcpv6_allocated_address_write(allocated_address, cur, serverInfo); + serverInfo->removeCb(interface, allocated_address, NULL); } } + if (serverInfo->removeCb) { // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix); @@ -312,18 +315,22 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { - int retVal = -1; - dhcpv6_gua_server_entry_s *serverInfo; + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->enableAddressAutonous = mode; - retVal = 0; } - return retVal; + serverInfo->enableAddressAutonous = mode; + if (mode) { + serverInfo->disableAddressListAllocation = autonomous_skip_list; + } else { + serverInfo->disableAddressListAllocation = false; + } + + return 0; } void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb) @@ -365,18 +372,18 @@ int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static */ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) { - int retVal = -1; dhcpv6_gua_server_entry_s *serverInfo; - if (maxClientCount == 0) { + if (maxClientCount == 0 || maxClientCount > MAX_SUPPORTED_ADDRESS_LIST_SIZE) { return -2; - } else { - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->maxSuppertedClients = maxClientCount; - retVal = 0; - } } - return retVal; + serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + + serverInfo->maxSupportedClients = maxClientCount; + + return 0; } /** SET Address Valid Lifetime parameter for allocated address, Default is 7200 seconds @@ -388,18 +395,17 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ */ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne) { - int retVal = -1; dhcpv6_gua_server_entry_s *serverInfo; if (validLifeTimne < 120) { - retVal = -2; - } else { - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - serverInfo->validLifetime = validLifeTimne; - retVal = 0; - } + return -2; } - return retVal; + serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + serverInfo->validLifetime = validLifeTimne; + + return 0; } #else @@ -422,11 +428,12 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) { (void) timeUpdateInSeconds; } -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { (void) interface; (void) guaPrefix; (void) mode; + (void) autonomous_skip_list; return -1; } diff --git a/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 2a236ad25422..8f8616f4f41d 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/source/DHCPv6_Server/DHCPv6_server_service.h @@ -66,8 +66,9 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); * /param interface interface id of this thread instance. * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id + * /param autonomous_skip_list true skip address list allocation when autonous mode is selected */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode); +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list); /* SET max accepted clients to server, Default is 200 diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index 2f19eb70a4e5..df8a72cb9141 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -49,17 +49,80 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) } entry->serverDynamic_DUID = server_duid_ptr; entry->serverDynamic_DUID_length = 16; - entry->clientIdSequence = 0; + entry->firstFreedId = 0; + entry->firstUnusedId = DHCP_ADDRESS_ID_START; entry->enableAddressAutonous = true; - entry->clientIdDefaultSuffics = 0x0000000; - entry->maxSuppertedClients = 200; + entry->disableAddressListAllocation = false; + entry->maxSupportedClients = 200; entry->validLifetime = 7200; entry->removeCb = NULL; entry->addCb = NULL; ns_list_init(&entry->allocatedAddressList); return entry; } -static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_alloacted_address_entry_t *entry) + +static uint16_t libdhcpv6_get_next_freed_id(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t last_allocated_id = DHCP_ADDRESS_ID_START - 1; + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + + if (last_allocated_id + 1 == cur->allocatedID) { + //Last and current plus 1 so normal order + last_allocated_id = cur->allocatedID; + continue; + } + + if ((cur->allocatedID - last_allocated_id) == 2) { + //one missing sequence between last and current + if (last_allocated_id + 1 == serverInfo->firstFreedId) { + //Skip + continue; + } + } else if (last_allocated_id + 1 == serverInfo->firstFreedId) { + //Skip first if it is last freedId + return last_allocated_id + 2; + } + + return last_allocated_id + 1; + } + //No more freed ID so return 0 + return 0; +} + +static uint16_t libdhcpv6_address_id_allocate(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t address_id; + if (serverInfo->firstFreedId) { + address_id = serverInfo->firstFreedId; + //Discover next free freed possible value + serverInfo->firstFreedId = libdhcpv6_get_next_freed_id(serverInfo); + } else { + //Allocated new ID + address_id = serverInfo->firstUnusedId++; + } + return address_id; +} + +static void libdhcpv6_gen_suffics_from_eui48(uint8_t *ptr, uint8_t *eui48) +{ + *ptr++ = *eui48++ ^ 2; + *ptr++ = *eui48++; + *ptr++ = *eui48++; + *ptr++ = 0xff; + *ptr++ = 0xfe; + *ptr++ = *eui48++; + *ptr++ = *eui48++; + *ptr = *eui48++; +} + +static void libdhcpv6_gen_suffics_from_allocated_id(uint8_t *ptr, uint8_t *server_unique_48_bit_id, uint16_t allocated_id) +{ + memcpy(ptr, server_unique_48_bit_id, 6); + common_write_16_bit(allocated_id, ptr + 6); +} + + +static uint16_t libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_t *entry) { //GENERATE ADDRESS uint8_t *ptr = entry->nonTemporalAddress; @@ -70,25 +133,78 @@ static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dh entry->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { memcpy(ptr, entry->linkId, 8); *ptr ^= 2; - } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { - *ptr++ = entry->linkId[0] ^ 2; - *ptr++ = entry->linkId[1]; - *ptr++ = entry->linkId[2]; - *ptr++ = 0xff; - *ptr++ = 0xfe; - *ptr++ = entry->linkId[3]; - *ptr++ = entry->linkId[4]; - *ptr = entry->linkId[5]; - } else { - ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); - ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); + return 0; } - } else { - ptr = common_write_32_bit((serverInfo->clientIdDefaultSuffics | 02000000), ptr); - ptr = common_write_32_bit((serverInfo->clientIdSequence + 2), ptr); + if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(ptr, entry->linkId); + return 0; + } + } + + uint16_t allocated_id = libdhcpv6_address_id_allocate(serverInfo); + libdhcpv6_gen_suffics_from_allocated_id(ptr, serverInfo->clientIdDefaultSuffics, allocated_id); + return allocated_id; +} + +static void libdhcpv6_address_free(dhcpv6_gua_server_entry_s *server_info, dhcpv6_allocated_address_entry_t *entry) +{ + ns_list_remove(&server_info->allocatedAddressList, entry); + if (!server_info->enableAddressAutonous) { + if (entry->allocatedID + 1 == server_info->firstUnusedId) { + server_info->firstUnusedId--; + } else if (server_info->firstFreedId == 0 || server_info->firstFreedId > entry->allocatedID) { + server_info->firstFreedId = entry->allocatedID; + } + } + ns_dyn_mem_free(entry); +} + +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + memcpy(ptr, serverInfo->guaPrefix, 8); + ptr += 8; + if (serverInfo->enableAddressAutonous) { + //Generate address from link layer address + if (address->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || + address->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { + memcpy(ptr, address->linkId, 8); + *ptr ^= 2; + return; + } else if (address->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(ptr, address->linkId); + return; + } } - serverInfo->clientIdSequence++; + //Generate from 16-bit allocate and default suffic's + libdhcpv6_gen_suffics_from_allocated_id(ptr, serverInfo->clientIdDefaultSuffics, address->allocatedID); +} + +static bool libdhcpv6_address_suffics_compare(const uint8_t *suffics, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + uint8_t allocated_suffics[8]; + if (serverInfo->enableAddressAutonous) { + //Generate address from link layer address + if (address->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || + address->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { + memcpy(allocated_suffics, address->linkId, 8); + allocated_suffics[0] ^= 2; + goto compare_suffics; + } else if (address->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { + libdhcpv6_gen_suffics_from_eui48(allocated_suffics, address->linkId); + goto compare_suffics; + } + } + //Generate from 16-bit allocate and default suffic's + libdhcpv6_gen_suffics_from_allocated_id(allocated_suffics, serverInfo->clientIdDefaultSuffics, address->allocatedID); + +compare_suffics: + if (memcmp(allocated_suffics, suffics, 8)) { + return false; + } + + return true; + } @@ -97,15 +213,16 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) //Check All allocated server inside this loop ns_list_foreach(dhcpv6_gua_server_entry_s, cur, &dhcpv6_gua_server_list) { //Check All allocated address in this module - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, address, &cur->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, address, &cur->allocatedAddressList) { //Update if (address->preferredLifetime) { if (address->preferredLifetime <= timeUpdateInSeconds) { //Stop use this address for leasequery and delete Route or address map - address->preferredLifetime = 0; if (cur->removeCb) { - cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix); + uint8_t allocated_address[16]; + libdhcpv6_allocated_address_write(allocated_address, address, cur); + cur->removeCb(cur->interfaceId, allocated_address, cur->guaPrefix); } } else { address->preferredLifetime -= timeUpdateInSeconds; @@ -113,8 +230,7 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) } if (address->lifetime <= timeUpdateInSeconds) { - ns_list_remove(&cur->allocatedAddressList, address); - ns_dyn_mem_free(address); + libdhcpv6_address_free(cur, address); } else { address->lifetime -= timeUpdateInSeconds; } @@ -187,6 +303,15 @@ dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t duid_length = libdhcpv6_duid_linktype_size(serverDUIDType) + 2; ptr = common_write_16_bit(serverDUIDType, ptr); memcpy(ptr, serverDUID, libdhcpv6_duid_linktype_size(serverDUIDType)); + //SET Defaultsuffics + if (libdhcpv6_duid_linktype_size(serverDUIDType) == 8) { + memcpy(entry->clientIdDefaultSuffics, serverDUID, 3); + memcpy(entry->clientIdDefaultSuffics + 3, serverDUID + 5, 3); + } else { + memcpy(entry->clientIdDefaultSuffics, serverDUID, 6); + } + + entry->clientIdDefaultSuffics[0] ^= 0x02; //SET DUID if (libdhcpv6_server_duid_set(entry, duid_ll, DHCPV6_DUID_LINK_LAYER_TYPE, duid_length) != 0) { @@ -208,7 +333,7 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); if (serverInfo) { if ((serverInfo->interfaceId == interfaceId) && (memcmp(serverInfo->guaPrefix, prefix, 8) == 0)) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { ns_list_remove(&serverInfo->allocatedAddressList, cur); ns_dyn_mem_free(cur); } @@ -219,26 +344,52 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t } } -static dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) +static void libdhcpv6_address_entry_lifetime_set(dhcpv6_allocated_address_entry_t *entry, uint32_t validLifetime) { - dhcpv6_alloacted_address_entry_t *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_alloacted_address_entry_t)); - if (entry) { - if (validLifetime != 0xffffffff) { - entry->lifetime = validLifetime; - entry->preferredLifetime = (validLifetime >> 1); - } else { - entry->lifetime = 0xffffffff; - entry->preferredLifetime = 0xffffffff; - } + if (validLifetime != 0xffffffff) { + entry->lifetime = validLifetime; + entry->preferredLifetime = (validLifetime >> 1); + } else { + entry->lifetime = 0xffffffff; + entry->preferredLifetime = 0xffffffff; } - return entry; } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +static void libdhcpv6_copy_allocated_entry_to_temp(dhcpv6_allocated_address_entry_t *cur, dhcpv6_allocated_address_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + libdhcpv6_allocated_address_write(address->nonTemporalAddress, cur, serverInfo); + memcpy(address->linkId, cur->linkId, 8); + address->T0 = cur->T0; + address->T1 = cur->T1; + address->iaID = cur->iaID; + address->lifetime = cur->lifetime; + address->preferredLifetime = cur->preferredLifetime; + address->linkType = cur->linkType; +} + + +static void libdhcpv6_copy_temp_to_allocated_entry(dhcpv6_allocated_address_entry_t *cur, dhcpv6_allocated_address_t *address, uint16_t allocated_id) +{ + memcpy(cur->linkId, address->linkId, 8); + cur->allocatedID = allocated_id; + cur->T0 = address->T0; + cur->T1 = address->T1; + cur->iaID = address->iaID; + cur->lifetime = address->lifetime; + cur->preferredLifetime = address->preferredLifetime; + cur->linkType = address->linkType; +} + +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { - ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { - return cur; + if (memcmp(serverInfo->guaPrefix, address, 8)) { + return NULL; + } + + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (libdhcpv6_address_suffics_compare(address + 8, cur, serverInfo) == 0) { + libdhcpv6_copy_allocated_entry_to_temp(cur, &serverInfo->tempAddressEntry, serverInfo); + return &serverInfo->tempAddressEntry; } } return NULL; @@ -246,49 +397,95 @@ dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcp void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - if (memcmp(cur->nonTemporalAddress, address, 16) == 0) { - ns_list_remove(&serverInfo->allocatedAddressList, cur); - ns_dyn_mem_free(cur); + if (memcmp(serverInfo->guaPrefix, address, 8)) { + return; + } + + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (libdhcpv6_address_suffics_compare(address + 8, cur, serverInfo) == 0) { + libdhcpv6_address_free(serverInfo, cur); return; } } } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) + +static void libdhcpv6_address_id_add_to_list(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_entry_t *allocated) +{ + if (serverInfo->firstUnusedId != allocated->allocatedID + 1) { + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (cur->allocatedID > allocated->allocatedID) { + //Add before new allocated + if (cur->link.prev) { + ns_list_add_before(&serverInfo->allocatedAddressList, cur, allocated); + } else { + //New first + ns_list_add_to_start(&serverInfo->allocatedAddressList, allocated); + } + return; + } + } + } + ns_list_add_to_end(&serverInfo->allocatedAddressList, allocated); +} + + +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) { - dhcpv6_alloacted_address_entry_t *newEntry = NULL; + dhcpv6_allocated_address_t *newEntry = NULL; + dhcpv6_allocated_address_entry_t *allocatedEntry = NULL; uint16_t duiLength = 6; if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { duiLength = 8; } - ns_list_foreach(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + + if (serverInfo->enableAddressAutonous && serverInfo->disableAddressListAllocation) { + //Accept allways when autonous + newEntry = &serverInfo->tempAddressEntry; + allocateNew = false; + } + + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { if (cur->linkType == linkType) { if (memcmp(cur->linkId, linkId, duiLength) == 0) { cur->iaID = iaID; - if (serverInfo->validLifetime != 0xffffffff) { - cur->lifetime = serverInfo->validLifetime ; - cur->preferredLifetime = (serverInfo->validLifetime >> 1); - } else { - cur->lifetime = 0xffffffff; - cur->preferredLifetime = 0xffffffff; - } - return cur; + libdhcpv6_address_entry_lifetime_set(cur, serverInfo->validLifetime); + libdhcpv6_copy_allocated_entry_to_temp(cur, &serverInfo->tempAddressEntry, serverInfo); + return &serverInfo->tempAddressEntry; } } } if (allocateNew) { - if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSuppertedClients) { - newEntry = libdhcpv6_address_entry_allocate(serverInfo->validLifetime); - if (newEntry) { - memcpy(newEntry->linkId, linkId, duiLength); - newEntry->linkType = linkType; - newEntry->iaID = iaID; - newEntry->T0 = T0; - newEntry->T1 = T1; - libdhcpv6_address_generate(serverInfo, newEntry); - ns_list_add_to_end(&serverInfo->allocatedAddressList, newEntry); + if (ns_list_count(&serverInfo->allocatedAddressList) < serverInfo->maxSupportedClients) { + allocatedEntry = ns_dyn_mem_alloc(sizeof(dhcpv6_allocated_address_entry_t)); + if (allocatedEntry) { + newEntry = &serverInfo->tempAddressEntry; + } + } + } + if (newEntry) { + + if (serverInfo->validLifetime != 0xffffffff) { + newEntry->lifetime = serverInfo->validLifetime; + newEntry->preferredLifetime = (serverInfo->validLifetime >> 1); + } else { + newEntry->lifetime = 0xffffffff; + newEntry->preferredLifetime = 0xffffffff; + } + memcpy(newEntry->linkId, linkId, duiLength); + newEntry->linkType = linkType; + newEntry->iaID = iaID; + newEntry->T0 = T0; + newEntry->T1 = T1; + uint16_t allocated_id = libdhcpv6_address_generate(serverInfo, newEntry); + if (!serverInfo->disableAddressListAllocation) { + libdhcpv6_copy_temp_to_allocated_entry(allocatedEntry, newEntry, allocated_id); + if (serverInfo->enableAddressAutonous) { + ns_list_add_to_end(&serverInfo->allocatedAddressList, allocatedEntry); + } else { + //Add to list to proper order + libdhcpv6_address_id_add_to_list(serverInfo, allocatedEntry); } } } diff --git a/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index ba17b340f5d7..3b4c0643e2e5 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/source/libDHCPv6/libDHCPv6_server.h @@ -28,29 +28,36 @@ #include "libDHCPv6/libDHCPv6.h" +#define MAX_SUPPORTED_ADDRESS_LIST_SIZE 0x0000fffd +#define DHCP_ADDRESS_ID_START 2 + typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info); -typedef struct dhcpv6_alloacted_address_entry_s { - uint8_t nonTemporalAddress[16]; +typedef struct dhcpv6_allocated_address_entry_s { uint8_t linkId[8]; /*!< Services UL64 */ - uint16_t linkType; uint32_t iaID; uint32_t T0; uint32_t T1; uint32_t preferredLifetime; uint32_t lifetime; + uint16_t linkType; + uint16_t allocatedID; ns_list_link_t link; /*!< List link entry */ -} dhcpv6_alloacted_address_entry_t; +} dhcpv6_allocated_address_entry_t; -typedef NS_LIST_HEAD(dhcpv6_alloacted_address_entry_t, link) dhcpv6_alloacted_address_list_t; -typedef struct thread_dhcpv6_server_data_s { - uint8_t prefix[8]; /*!< Services Prefix */ - uint16_t maxSuppertedClients; - uint32_t clientIdSequence; /*!< Define */ - dhcpv6_alloacted_address_list_t allocatedAddressList; - ns_list_link_t link; /*!< List link entry */ -} dhcpv6_server_data_entry_t; +typedef struct dhcpv6_allocated_address_s { + uint8_t nonTemporalAddress[16]; + uint8_t linkId[8]; /*!< Services UL64 */ + uint16_t linkType; + uint32_t iaID; + uint32_t T0; + uint32_t T1; + uint32_t preferredLifetime; + uint32_t lifetime; +} dhcpv6_allocated_address_t; + +typedef NS_LIST_HEAD(dhcpv6_allocated_address_entry_t, link) dhcpv6_allocated_address_list_t; typedef struct dhcp_address_cache_update { uint8_t *allocatedAddress; @@ -62,19 +69,22 @@ typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache typedef struct dhcpv6_gua_server_entry_s { int8_t interfaceId; - bool enableAddressAutonous; + bool enableAddressAutonous: 1; + bool disableAddressListAllocation: 1; uint16_t socketInstance_id; uint8_t guaPrefix[8]; uint8_t serverDynamic_DUID_length; - uint32_t maxSuppertedClients; - uint32_t clientIdDefaultSuffics; - uint32_t clientIdSequence; /*!< Define */ + uint32_t maxSupportedClients; + uint8_t clientIdDefaultSuffics[6]; + uint16_t firstFreedId; + uint16_t firstUnusedId; /*!< This is first unused Id */ uint32_t validLifetime; dhcp_duid_options_params_t serverDUID; uint8_t *serverDynamic_DUID; dhcp_address_prefer_remove_cb *removeCb; dhcp_address_add_notify_cb *addCb; - dhcpv6_alloacted_address_list_t allocatedAddressList; + dhcpv6_allocated_address_list_t allocatedAddressList; + dhcpv6_allocated_address_t tempAddressEntry; ns_list_link_t link; /*!< List link entry */ } dhcpv6_gua_server_entry_s; @@ -84,10 +94,11 @@ int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *d void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId); void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds); void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(int8_t interfaceId, const uint8_t *prefixPtr); dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr); -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo); #else #define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL diff --git a/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c b/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c index 3cf90d0d8f82..b4439ff91253 100644 --- a/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c +++ b/test/nanostack/unittest/stub/dhcpv6_server_service_stub.c @@ -95,7 +95,7 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], * /param guaPrefix Prefix which will be removed * /param mode true trig autonous mode, false define address by default suffics + client id */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode) +int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { return 0; } diff --git a/test/nanostack/unittest/stub/libDHCPv6_server_stub.c b/test/nanostack/unittest/stub/libDHCPv6_server_stub.c index b7e956b4de7d..a82dfa5c9780 100644 --- a/test/nanostack/unittest/stub/libDHCPv6_server_stub.c +++ b/test/nanostack/unittest/stub/libDHCPv6_server_stub.c @@ -47,12 +47,12 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t { } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) +dhcpv6_allocated_address_entry_t *libdhcpv6_address_entry_allocate(uint32_t validLifetime) { return NULL; } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +dhcpv6_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { return NULL; } @@ -62,7 +62,7 @@ void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverI } -dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) +dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *linkId, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew) { return NULL; } @@ -77,3 +77,8 @@ bool libdhcpv6_gua_server_list_empty(void) return true; } +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo) +{ + +} +