From 856da9bd60f3409f55b21d8951bb3cc010668396 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 23 Feb 2021 12:25:25 +0200 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 91f3ff6d7f..25b9124cd2 25b9124cd2 Merge remote-tracking branch 'origin/release_internal' into release_external c825b04555 Corrected covery warning on delay_us multiplication be63bbb145 Updated changelog 77a76c78bb Corrected nw size set on automatic mode 65e6c2db7a Updated unit tests 16e340286a Added waiting queue to EAPOL authentications to Border Router b9c0b7d2ac Wi-SUN border router starts faster in static configuration 2f427e115a Local repair start and stop clear advertised_dodag_membership_since_last_repair when state is updated. 0a01ab19a4 RPL dio send update dd3996382c Wi-SUN Border router uses Static address as DODAGID 7a3c8335b0 Additional check to detect parent connection problem ffe48c93e5 WS management: domain configuration functions implemented (#2567) 5e9ac4ece8 Added new Callback to RPL indicate Multicast DIS received from RPL Parent 85b949e9c2 Bootstrap and EAPOL treats all MAC TX failure causes similarly b57d9bcd66 Add support for anonymous addressing in Wi-SUN border router (#2565) 7400c8bc9e CFG: API for PHY mode id and channel plan id get & validate (#2564) 2832fe8c27 Added Socket reference limitter 890aad12f1 Wi-SUN MTU size update and IPv6 minium MTU routing skip 3ad28c1cfc Added throttling of number of simultaneous EAPOL authentications 0b84299edb Source route handler call Wi-Sun border router alive function. c8343b1a01 Added support for dynamic RPL default lifetime d258068555 Iotthd 4478 (#2560) 7ca6c24b67 Enable and modify memory limits for packet receiving e2b028d9ae Close CHANGELOG.md for v12.8.1 (#2557) git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: 25b9124cd240de3609ff913aa7dadf56d6c0ae16 --- nanostack/ws_bbr_api.h | 4 + nanostack/ws_management_api.h | 161 +++++--- .../Generic/protocol_6lowpan_bootstrap.c | 2 +- source/6LoWPAN/Thread/thread_management_if.c | 2 +- source/6LoWPAN/ws/ws_bbr_api.c | 104 ++++-- source/6LoWPAN/ws/ws_bbr_api_internal.h | 4 +- source/6LoWPAN/ws/ws_bootstrap.c | 209 ++++++++++- source/6LoWPAN/ws/ws_cfg_settings.c | 39 +- source/6LoWPAN/ws/ws_cfg_settings.h | 4 +- source/6LoWPAN/ws/ws_common.c | 10 + source/6LoWPAN/ws/ws_common.h | 3 + source/6LoWPAN/ws/ws_common_defines.h | 8 + source/6LoWPAN/ws/ws_config.h | 12 +- source/6LoWPAN/ws/ws_empty_functions.c | 27 +- source/6LoWPAN/ws/ws_management_api.c | 77 +++- source/6LoWPAN/ws/ws_pae_auth.c | 185 +++++++--- source/6LoWPAN/ws/ws_pae_auth.h | 16 +- source/6LoWPAN/ws/ws_pae_controller.c | 38 +- source/6LoWPAN/ws/ws_pae_controller.h | 22 +- source/6LoWPAN/ws/ws_pae_lib.c | 79 ++-- source/6LoWPAN/ws/ws_pae_lib.h | 56 +-- source/6LoWPAN/ws/ws_pae_supp.c | 4 +- source/Common_Protocols/ipv6.c | 13 +- source/Common_Protocols/ipv6.h | 2 +- source/Core/include/ns_monitor.h | 4 +- source/Core/include/ns_socket.h | 4 + source/Core/ns_monitor.c | 67 +++- source/Core/ns_socket.c | 53 ++- source/DHCPv6_Server/DHCPv6_Server_service.c | 33 +- source/DHCPv6_Server/DHCPv6_server_service.h | 12 +- source/MAC/IEEE802_15_4/mac_data_buffer.h | 3 + source/MAC/IEEE802_15_4/mac_defines.h | 3 +- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 23 +- source/MAC/IEEE802_15_4/mac_mcps_sap.h | 1 + source/MAC/IEEE802_15_4/mac_pd_sap.c | 22 +- source/MPL/mpl.c | 1 + source/RPL/rpl_control.c | 28 +- source/RPL/rpl_control.h | 5 +- source/RPL/rpl_data.c | 8 + source/RPL/rpl_upward.c | 71 +++- source/Security/kmp/kmp_api.h | 4 +- .../protocols/key_sec_prot/key_sec_prot.c | 2 +- source/Security/protocols/sec_prot.h | 2 +- source/Security/protocols/sec_prot_cfg.h | 8 +- source/Service_Libs/fhss/fhss_ws.c | 4 +- source/Service_Libs/utils/ns_conf.c | 4 +- source/ipv6_stack/ipv6_routing_table.c | 13 +- source/libDHCPv6/libDHCPv6_server.c | 349 +++++++----------- source/libDHCPv6/libDHCPv6_server.h | 38 +- 49 files changed, 1212 insertions(+), 631 deletions(-) diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index 408eb7e3e9..6347e2c95c 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -99,6 +99,7 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id); #define BBR_REQUIRE_DAO_REFRESH 0x0000 /**< Deprecated DAO Refresh is now the default functionality*/ #define BBR_PERIODIC_VERSION_INC 0x0010 /**< Increment PAN version number Periodically*/ #define BBR_GUA_SLAAC 0x0020 /**< in Global prefix use SLAAC address generation to reduce traffic during bootstrap */ +#define BBR_DHCP_ANONYMOUS 0x0040 /**< Generate anonymous addresses from DHCP server */ /** * Configure border router features. @@ -108,6 +109,9 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id); * BBR_ULA_C Configure Mesh local ULA prefix with SLAAC address * BBR_GUA_ROUTE Add more specific route for GUA * BBR_BB_WAIT Start Wi-SUN network only when backbone is ready + * BBR_DHCP_ANONYMOUS if true give anonymous address (16 bit suffix) to + * optimize data in RF interface (saves 12 bytes per hop) + * or false to reduce RAM usage in Border router as assigned address list is not needed (40 bytes per device). * * By default Wi-SUN network is started and is treated as separate interface even if backbone is not available. * diff --git a/nanostack/ws_management_api.h b/nanostack/ws_management_api.h index d11409adc0..f506c37995 100644 --- a/nanostack/ws_management_api.h +++ b/nanostack/ws_management_api.h @@ -95,6 +95,30 @@ extern "C" { */ #define WS_MANAGEMENT_API_VER_2 /**< Management API version */ +/** + * Deprecated! + * Configure PHY mode ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1. + * + * \param interface_id Network interface ID. + * \param phy_mode_id PHY mode ID. Default 255 (not used). + * + * \return 0, Init OK. + * \return <0 Init fail. + */ +#define ws_management_phy_mode_id_set(interface_id, phy_mode_id) ws_management_domain_configuration_set(interface_id, 0, phy_mode_id, 0) + +/** + * Deprecated! + * Configure Channel plan ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1. + * + * \param interface_id Network interface ID. + * \param channel_plan_id Channel plan ID. Default 255 (not used). + * + * \return 0, Init OK. + * \return <0 Init fail. + */ +#define ws_management_channel_plan_id_set(interface_id, channel_plan_id) ws_management_domain_configuration_set(interface_id, 0, 0, channel_plan_id) + /** * \brief Struct ws_statistics defines the Wi-SUN statistics storage structure. */ @@ -187,80 +211,107 @@ int ws_management_network_name_validate( char *network_name_ptr); /** - * Configure PHY mode ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1. + * Set domain configuration of Wi-SUN stack. * * Change the default configuration for Wi-SUN PHY operation. * * Supported values: - * FSK without FEC: - * PHY mode ID | Symbol Rate (kbps) | Modulation Index - * 1 50 0.5 - * 2 50 1.0 - * 3 100 0.5 - * 4 100 1.0 - * 5 150 0.5 - * 6 200 0.5 - * 7 200 1.0 - * 8 300 0.5 + * Regulatory domain: "NA"(0x01), "KR"(0x09), "EU"(0x03), "IN"(0x05), "BZ"(0x07), "JP"(0x09), "WW"(0x00) * - * FSK with FEC: - * PHY mode ID | Symbol Rate (kbps) | Modulation Index - * 17 50 0.5 - * 18 50 1.0 - * 19 100 0.5 - * 20 100 1.0 - * 21 150 0.5 - * 22 200 0.5 - * 23 200 1.0 - * 24 300 0.5 + * PHY mode ID: + * FSK without FEC: + * PHY mode ID | Symbol Rate (kbps) | Modulation Index + * 1 50 0.5 + * 2 50 1.0 + * 3 100 0.5 + * 4 100 1.0 + * 5 150 0.5 + * 6 200 0.5 + * 7 200 1.0 + * 8 300 0.5 * - * OFDM: - * PHY mode ID | Option | MCS | Data rate (kbps) - * 34 1 2 400 - * 35 1 3 800 - * 36 1 4 1200 - * 37 1 5 1600 - * 38 1 6 2400 - * 51 2 3 400 - * 52 2 4 600 - * 53 2 5 800 - * 54 2 6 1200 - * 68 3 4 300 - * 69 3 5 400 - * 70 3 6 600 - * 84 4 4 150 - * 85 4 5 200 - * 86 4 6 300 + * FSK with FEC: + * PHY mode ID | Symbol Rate (kbps) | Modulation Index + * 17 50 0.5 + * 18 50 1.0 + * 19 100 0.5 + * 20 100 1.0 + * 21 150 0.5 + * 22 200 0.5 + * 23 200 1.0 + * 24 300 0.5 * - * if value of 255 is given then previous value is used. + * OFDM: + * PHY mode ID | Option | MCS | Data rate (kbps) + * 34 1 2 400 + * 35 1 3 800 + * 36 1 4 1200 + * 37 1 5 1600 + * 38 1 6 2400 + * 51 2 3 400 + * 52 2 4 600 + * 53 2 5 800 + * 54 2 6 1200 + * 68 3 4 300 + * 69 3 5 400 + * 70 3 6 600 + * 84 4 4 150 + * 85 4 5 200 + * 86 4 6 300 + * + * Channel plan ID: + * North America (NA): (1), (2), (5) + * Brazil (BZ): (1), (2), (5) + * + * If value of 0 is given then previous value is used. + * If value of 255 is given then default value is used. * * \param interface_id Network interface ID. - * \param phy_mode_id PHY mode ID. Default 255 (not used). + * \param regulatory_domain Regulatory domain. + * \param phy_mode_id PHY mode ID. + * \param channel_plan_id Channel plan ID. * - * \return 0, Init OK. - * \return <0 Init fail. + * \return 0, OK. + * \return <0 Fail. */ -int ws_management_phy_mode_id_set( +int ws_management_domain_configuration_set( int8_t interface_id, - uint8_t phy_mode_id); + uint8_t regulatory_domain, + uint8_t phy_mode_id, + uint8_t channel_plan_id); /** - * Configure Channel plan ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1. - * - * Change the default channel configuration for Wi-SUN. - * - * Supported values: TBD - * - * if value of 255 is given then previous value is used. + * Get domain configuration of Wi-SUN stack. * * \param interface_id Network interface ID. - * \param channel_plan_id Channel plan ID. Default 255 (not used). + * \param regulatory_domain Regulatory domain. + * \param phy_mode_id PHY mode ID. + * \param channel_plan_id Channel plan ID. * - * \return 0, Init OK. - * \return <0 Init fail. + * \return 0, OK. + * \return <0 Fail. */ -int ws_management_channel_plan_id_set( +int ws_management_domain_configuration_get( int8_t interface_id, + uint8_t *regulatory_domain, + uint8_t *phy_mode_id, + uint8_t *channel_plan_id); + +/** + * Validate domain configuration of Wi-SUN stack. + * + * \param interface_id Network interface ID. + * \param regulatory_domain Regulatory domain. + * \param phy_mode_id PHY mode ID. + * \param channel_plan_id Channel plan ID. + * + * \return 0, OK. + * \return <0 Fail. + */ +int ws_management_domain_configuration_validate( + int8_t interface_id, + uint8_t regulatory_domain, + uint8_t phy_mode_id, uint8_t channel_plan_id); /** diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index 0a21788cc2..11a2a8d989 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -2184,7 +2184,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t * // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, NULL, cur); } // Send unicast DIS to coordinator nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); diff --git a/source/6LoWPAN/Thread/thread_management_if.c b/source/6LoWPAN/Thread/thread_management_if.c index 7409f53a90..2a35d85dfe 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, false); + return DHCPv6_server_service_set_address_generation_anonymous(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 75a1178bfc..7a86817450 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -197,7 +197,7 @@ static void ws_bbr_rpl_version_increase(protocol_interface_info_entry_t *cur) 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) +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, uint32_t lifetime) { if (imin == 0 || doubling == 0) { // use default values @@ -205,12 +205,33 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8 doubling = WS_RPL_DIO_DOUBLING_SMALL; redundancy = WS_RPL_DIO_REDUNDANCY_SMALL; } + uint8_t lifetime_unit = 60; + uint8_t default_lifetime; + + if (lifetime == 0) { + // 2 hours default lifetime + lifetime = 120 * 60; + } else if (lifetime <= 250 * 60) { + // Lifetime unit of 60 is ok up to 4 hours + } else if (lifetime <= 250 * 120) { + //more than 4 hours needs larger lifetime unit + lifetime_unit = 120; + } else if (lifetime <= 250 * 240) { + lifetime_unit = 240; + } else { + // Maximum lifetime is 16 hours 40 minutes + lifetime = 250 * 240; + lifetime_unit = 240; + } + default_lifetime = lifetime / lifetime_unit; if (rpl_conf.dio_interval_min == imin && rpl_conf.dio_interval_doublings == doubling && rpl_conf.dio_redundancy_constant == redundancy && rpl_conf.dag_max_rank_increase == dag_max_rank_increase && - rpl_conf.min_hop_rank_increase == min_hop_rank_increase) { + rpl_conf.min_hop_rank_increase == min_hop_rank_increase && + rpl_conf.default_lifetime == default_lifetime && + rpl_conf.lifetime_unit == lifetime_unit) { // Same values no update needed return; } @@ -220,6 +241,8 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8 rpl_conf.dio_redundancy_constant = redundancy; rpl_conf.dag_max_rank_increase = dag_max_rank_increase; rpl_conf.min_hop_rank_increase = min_hop_rank_increase; + rpl_conf.default_lifetime = default_lifetime; + rpl_conf.lifetime_unit = lifetime_unit; if (protocol_6lowpan_rpl_root_dodag) { rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf); @@ -343,6 +366,34 @@ static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *u addr_policy_table_delete_entry(ula_prefix, 64); } +/* + * 0 static non rooted self generated own address + * 1 static address with backbone connectivity + */ +static uint8_t *ws_bbr_bb_static_prefix_get(uint8_t *dodag_id_ptr) +{ + + /* Get static ULA prefix if we have configuration in backbone and there is address we use that. + * + * If there is no address we can use our own generated ULA as a backup ULA + */ + + protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id); + + if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) { + ns_list_foreach(if_address_entry_t, addr, &bb_interface->ip_addresses) { + if (bitsequal(addr->address, bb_interface->ipv6_configure->static_prefix64, 64)) { + // static address available in interface copy the prefix and return the address + if (dodag_id_ptr) { + memcpy(dodag_id_ptr, bb_interface->ipv6_configure->static_prefix64, 8); + } + return addr->address; + } + } + } + return NULL; +} + static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur) { @@ -350,6 +401,14 @@ static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur) // address generated return 0; } + + uint8_t *static_address_ptr = ws_bbr_bb_static_prefix_get(NULL); + if (static_address_ptr) { + memcpy(current_dodag_id, static_address_ptr, 16); + tr_info("BBR Static DODAGID %s", trace_ipv6(current_dodag_id)); + return 0; + } + // This address is only used if no other address available. if_address_entry_t *add_entry = ws_bbr_slaac_generate(cur, static_dodag_id_prefix); if (!add_entry) { @@ -362,29 +421,6 @@ static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur) return 0; } -/* - * 0 static non rooted self generated own address - * 1 static address with backbone connectivity - */ -static void ws_bbr_bb_static_prefix_get(uint8_t *dodag_id_ptr) -{ - - /* Get static ULA prefix if we have configuration in backbone and there is address we use that. - * - * If there is no address we can use our own generated ULA as a backup ULA - */ - - protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id); - - if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) { - if (protocol_address_prefix_cmp(bb_interface, bb_interface->ipv6_configure->static_prefix64, 64)) { - memcpy(dodag_id_ptr, bb_interface->ipv6_configure->static_prefix64, 8); - } - } - return; -} - - static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_ptr) { uint8_t global_address[16]; @@ -500,8 +536,10 @@ 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); - //Enable SLAAC mode to border router - DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true, false); + //Check for anonymous mode + bool anonymous = (configuration & BBR_DHCP_ANONYMOUS) ? true : false; + + DHCPv6_server_service_set_address_generation_anonymous(cur->id, global_id, anonymous, false); DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, 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); @@ -510,6 +548,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8 ws_dhcp_client_address_request(cur, global_id, ll); } + static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id) { if (!cur) { @@ -626,9 +665,16 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) */ if ((configuration & BBR_ULA_C) == 0 && memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) { //Global prefix not available count if backup ULA should be created + uint32_t prefix_wait_time = BBR_BACKUP_ULA_DELAY; global_prefix_unavailable_timer += BBR_CHECK_INTERVAL; - tr_debug("Check for backup prefix %"PRIu32"", global_prefix_unavailable_timer); - if (global_prefix_unavailable_timer >= BBR_BACKUP_ULA_DELAY) { + + if (NULL != ws_bbr_bb_static_prefix_get(NULL)) { + // If we have a static configuration we activate it faster. + prefix_wait_time = 40; + } + + tr_debug("Check for backup prefix %"PRIu32" / %"PRIu32"", prefix_wait_time, global_prefix_unavailable_timer); + if (global_prefix_unavailable_timer >= prefix_wait_time) { if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) { tr_info("start using backup prefix %s", trace_ipv6_prefix(local_prefix, 64)); } diff --git a/source/6LoWPAN/ws/ws_bbr_api_internal.h b/source/6LoWPAN/ws/ws_bbr_api_internal.h index 78892b9f1d..24779fdc22 100644 --- a/source/6LoWPAN/ws/ws_bbr_api_internal.h +++ b/source/6LoWPAN/ws/ws_bbr_api_internal.h @@ -29,7 +29,7 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur); uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur); -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); +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, uint32_t lifetime); void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint32_t dhcp_address_lifetime); @@ -45,7 +45,7 @@ void ws_bbr_init(protocol_interface_info_entry_t *interface); #define ws_bbr_seconds_timer( cur, seconds) #define ws_bbr_pan_version_increase(cur) #define ws_bbr_pan_size(cur) 0 -#define ws_bbr_rpl_config( cur, 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, lifetime) #define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime) #define ws_bbr_ready_to_start(cur) true #define ws_bbr_backbone_address_get(address) 0 diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 03a646d854..d9f5dcd97d 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -28,6 +28,7 @@ #include "mac_common_defines.h" #include "sw_mac.h" #include "ccmLIB.h" +#include "Core/include/ns_monitor.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" @@ -103,6 +104,7 @@ static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t * static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name); static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64); static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id); +static bool ws_bootstrap_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur); 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); @@ -110,6 +112,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr, bool clear_list); +static void ws_bootstrap_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance); static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); @@ -118,6 +121,7 @@ static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t static void ws_bootstrap_asynch_trickle_stop(protocol_interface_info_entry_t *cur); static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur); +static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur); typedef enum { WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ @@ -1010,6 +1014,30 @@ static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notif } +static void ws_bootstrap_memory_configuration() +{ + /* Configure memory limits for garbage collection based on total memory size + * Starting from these values + * 5% for High mark + * 2% for critical mark + * 1% for Routing limit + * Memory High Critical Drop routing + * 32K RAM 3200 bytes 1280 Bytes 1024 bytes + * 64K RAM 3200 bytes 1280 Bytes 1024 bytes + * 128K RAM 6400 bytes 2560 Bytes 1280 bytes + * 320K RAM 16000 byte 6400 Bytes 3200 bytes + * 640K RAM 32000 byte 12800 Bytes 6400 bytes + * 1000K RAM 50000 bytes 20000 Bytes 10000 bytes + * 4000K RAM 120000 bytes 40000 Bytes 10000 bytes + * */ + // In small memory devices there needs to lower limit so that there some change to be usable + // and there is no use for having very large values on high memory devices + ns_monitor_packet_ingress_rate_limit_by_memory(1024, 10000, 1); + + ns_monitor_heap_gc_threshold_set(3200, 120000, 95, 1280, 40000, 98); + return; +} + static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) { @@ -1066,7 +1094,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC); dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb); - + // Configure memory limits and garbage collection values; + ws_bootstrap_memory_configuration(); ws_nud_table_reset(cur); ws_bootstrap_candidate_table_reset(cur); @@ -1590,6 +1619,13 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); } + + if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); + if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + ws_bootstrap_parent_confirm(cur, NULL); + } + } } @@ -1732,7 +1768,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry // restart PAN version timer //Check Here Do we have a selected Primary parent if (!cur->ws_info->configuration_learned || cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { - cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; + ws_common_border_router_alive_update(cur); } cur->ws_info->pan_information.pan_version = pan_version; @@ -1776,7 +1812,12 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); } - + if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); + if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + ws_bootstrap_parent_confirm(cur, NULL); + } + } /* * A consistent transmission is defined as a PAN Configuration Solicit with @@ -2290,11 +2331,11 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) ret_val = -4; goto init_fail; } - if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated) < 0) { + if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated, &ws_bootstrap_congestion_get) < 0) { ret_val = -4; goto init_fail; } - if (ws_pae_controller_configure(cur, &cur->ws_info->cfg->sec_timer, &cur->ws_info->cfg->sec_prot) < 0) { + if (ws_pae_controller_configure(cur, &cur->ws_info->cfg->sec_timer, &cur->ws_info->cfg->sec_prot, &cur->ws_info->cfg->timing) < 0) { ret_val = -4; goto init_fail; } @@ -2310,6 +2351,8 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) goto init_fail; } + cur->ipv6_neighbour_cache.link_mtu = cur->max_link_mtu = WS_MPX_MAX_MTU; + cur->if_up = ws_bootstrap_up; cur->if_down = ws_bootstrap_down; cur->ws_info->neighbor_storage = neigh_info; @@ -2576,6 +2619,63 @@ static void ws_address_parent_update(protocol_interface_info_entry_t *interface) ws_address_registration_update(interface, NULL); } +static void ws_bootstrap_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) +{ + /* Possible problem with the parent connection + * Give some time for parent to rejoin and confirm the connection with ARO and DAO + */ + const rpl_dodag_conf_t *config = NULL; + uint32_t Imin_secs = 0; + + if (!ws_bootstrap_state_active(cur)) { + // If we are not in Active state no need to confirm parent + return; + } + + tr_info("RPL parent confirm"); + + if (!instance) { + // If we dont have instance we take any available to get reference + instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); + } + + if (instance) { + config = rpl_control_get_dodag_config(instance); + } + + if (config) { + //dio imin Period caluclate in seconds + uint32_t Imin_ms = config->dio_interval_min < 32 ? (1ul << config->dio_interval_min) : 0xfffffffful; + //Covert to seconds and multiple by 2 so we give time to recovery so divide by 500 do that operation + Imin_secs = (Imin_ms + 499) / 500; + + if (Imin_secs > 0xffff) { + Imin_secs = 0xffff; + } + } + if (Imin_secs == 0) { + // If we dont have RPL configuration we assume conservative value + Imin_secs = 60; + } + + /*Speed up the ARO registration*/ + if (cur->ws_info->aro_registration_timer > Imin_secs) { + cur->ws_info->aro_registration_timer = Imin_secs; + } +} + +static void ws_rpl_parent_dis_callback(const uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance) +{ + (void) ll_parent_address; + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + return; + } + //Multicast DIS from parent indicate that Parent is not valid in short time window possible + ws_bootstrap_parent_confirm(cur, instance); +} + + static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) { @@ -2619,9 +2719,7 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) } // After successful DAO ACK connection to border router is verified - cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; - - + ws_common_border_router_alive_update(cur); } if (!cur->ws_info->trickle_pa_running || !cur->ws_info->trickle_pc_running) { @@ -2643,10 +2741,14 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) } else if (event == RPL_EVENT_LOCAL_REPAIR_START) { tr_debug("RPL local repair start"); - //Disable Asynchs - ws_bootstrap_asynch_trickle_stop(cur); - ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN); - + //Disable Async and go to state 4 to confirm parent connection + ws_bootstrap_parent_confirm(cur, NULL); + // Move to state 4 if we see issues with primary parent + if (ws_bootstrap_state_active(cur)) { + tr_info("Move state 4 to wait parent connection confirmation"); + ws_bootstrap_rpl_scan_start(cur); + ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN); + } } else if (event == RPL_EVENT_DAO_PARENT_ADD) { ws_address_parent_update(cur); } @@ -2861,7 +2963,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, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback, ws_rpl_parent_dis_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 @@ -3070,7 +3172,7 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_ if (result == AUTH_RESULT_OK) { tr_debug("authentication success"); ws_bootstrap_event_configuration_start(cur); - } else if (result == AUTH_RESULT_ERR_TX_NO_ACK) { + } else if (result == AUTH_RESULT_ERR_TX_ERR) { // eapol parent selected is not working tr_debug("authentication TX failed"); @@ -3112,6 +3214,70 @@ static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface return previous_eui_64; } +static bool ws_bootstrap_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp) +{ + if (interface_ptr == NULL || interface_ptr->random_early_detection == NULL) { + return false; + } + + bool return_value = false; + static struct red_info_s *red_info = NULL; + uint16_t average = 0; + uint8_t active_max = 0; + + //TODO implement API for HEAP info request + uint32_t heap_size; + const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat(); + if (mem_stats) { + heap_size = mem_stats->heap_sector_size; + } else { + heap_size = 0; + } + + /* + * For different memory sizes the max simultaneous authentications will be + * 32k: (32k / 50k) * 2 + 1 = 1 + * 65k: (65k / 50k) * 2 + 1 = 3 + * 250k: (250k / 50k) * 2 + 1 = 11 + * 1000k: (1000k / 50k) * 2 + 1 = 41 + * 2000k: (2000k / 50k) * 2 + 1 = 50 (upper limit) + */ + active_max = (heap_size / 50000) * 2 + 1; + if (active_max > 50) { + active_max = 50; + } + + // Maximum for active supplicants based on memory reached, fail + if (active_supp >= active_max) { + return_value = true; + goto congestion_get_end; + } + + // Always allow at least five negotiations (if memory does not limit) + if (active_supp < 5) { + goto congestion_get_end; + } + + if (red_info == NULL) { + red_info = random_early_detection_create( + interface_ptr->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_min, + interface_ptr->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_max, + 100, RED_AVERAGE_WEIGHT_DISABLED); + } + if (red_info == NULL) { + goto congestion_get_end; + } + + average = random_early_detetction_aq_read(interface_ptr->random_early_detection); + average = random_early_detetction_aq_calc(red_info, average); + return_value = random_early_detection_congestion_check(red_info); + +congestion_get_end: + tr_info("Active supplicant limit, active: %i max: %i averageQ: %i drop: %s", active_supp, active_max, average, return_value ? "T" : "F"); + + return return_value; +} + // Start configuration learning static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur) { @@ -3134,18 +3300,18 @@ static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) { tr_debug("Start RPL learn"); + // Stop Trickle timers + ws_bootstrap_asynch_trickle_stop(cur); + // routers wait until RPL root is contacted ws_bootstrap_state_change(cur, ER_RPL_SCAN); + // Change state as the state is checked in state machine + cur->ws_info->rpl_state = RPL_EVENT_LOCAL_REPAIR_START; //For Large network and medium should do passive scan if (ws_cfg_network_config_get(cur) > CONFIG_SMALL) { // 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); } - /* While in Join State 4, if a non Border Router determines it has been unable to communicate with the PAN Border - * Router for an interval of PAN_TIMEOUT, a node MUST assume failure of the PAN Border Router and MUST - * Transition to Join State 1 - */ - cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; } /* @@ -3500,6 +3666,11 @@ static void ws_bootstrap_event_handler(arm_event_s *event) ws_bootstrap_event_routing_ready(cur); } else { ws_bootstrap_rpl_scan_start(cur); + /* While in Join State 4, if a non Border Router determines it has been unable to communicate with the PAN Border + * Router for an interval of PAN_TIMEOUT, a node MUST assume failure of the PAN Border Router and MUST + * Transition to Join State 1 + */ + ws_common_border_router_alive_update(cur); } break; case WS_ROUTING_READY: diff --git a/source/6LoWPAN/ws/ws_cfg_settings.c b/source/6LoWPAN/ws/ws_cfg_settings.c index 40e46940f3..0c81ba7acc 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -301,6 +301,8 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ set_function(&nw_size_cfg); } + uint8_t cfg_network_size = cfg->network_size; + /* If no longer in an automatic network size mode, frees automatic configuration, so that new configuration is set */ if (nw_size_external_cfg && old_network_size == NETWORK_SIZE_AUTOMATIC) { @@ -309,7 +311,7 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ } uint8_t set_flags = 0; - if (cfg->network_size == NETWORK_SIZE_AUTOMATIC) { + if (cfg_network_size == NETWORK_SIZE_AUTOMATIC) { set_flags = CFG_FLAGS_DISABLE_VAL_SET; } /* Sets values if changed or network size has been previously automatic (to make sure @@ -336,7 +338,7 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ } // If is in an automatic network size mode, updates automatic configuration - if (cfg->network_size == NETWORK_SIZE_AUTOMATIC && cur) { + if (cfg_network_size == NETWORK_SIZE_AUTOMATIC && cur) { ws_cfg_network_size_configure(cur, cur->ws_info->pan_information.pan_size); } return CFG_SETTINGS_OK; @@ -448,6 +450,7 @@ static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL; // EAPOL configuration @@ -456,8 +459,6 @@ static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; - cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL; - cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER; cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -492,6 +493,7 @@ static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10 cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_MEDIUM; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM; // EAPOL configuration @@ -500,8 +502,6 @@ static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; - cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM; - cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER; cfg->sec_prot.initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -535,6 +535,7 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10 cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_LARGE; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE; // EAPOL configuration @@ -543,8 +544,6 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE; - cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE; - cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER; cfg->sec_prot.initial_key_imin = LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -579,6 +578,7 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg) cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_XLARGE; // 10 cfg->bbr.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_XLARGE; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_LARGE; // EAPOL configuration @@ -587,8 +587,6 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg) cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE; - cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE; - cfg->sec_prot.initial_key_retry_delay = NONE_INITIAL_KEY_RETRY_TIMER; cfg->sec_prot.initial_key_imin = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -622,6 +620,7 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) cfg->bbr.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled cfg->bbr.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE; cfg->bbr.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE; + cfg->bbr.rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME; cfg->bbr.dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_SMALL; // EAPOL configuration @@ -630,8 +629,6 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; - cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL; - cfg->sec_prot.initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER; cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -698,6 +695,7 @@ int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, w } ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_gen_cfg_t), "gen"); + cfg->network_size = new_cfg->network_size; if (&cfg->network_name != &new_cfg->network_name) { strncpy(cfg->network_name, new_cfg->network_name, 32); } @@ -883,6 +881,7 @@ int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t * cur->ws_info->trickle_params_pan_discovery.Imax = new_cfg->disc_trickle_imax * 10; cur->ws_info->trickle_params_pan_discovery.k = new_cfg->disc_trickle_k; cur->ws_info->trickle_params_pan_discovery.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE; + ws_pae_controller_configure(cur, NULL, NULL, new_cfg); } if (cfg == new_cfg) { @@ -909,6 +908,7 @@ static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg) cfg->dio_redundancy_constant = 10; cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl_default_lifetime = WS_RPL_DEFAULT_LIFETIME_MEDIUM; cfg->dhcp_address_lifetime = WS_DHCP_ADDRESS_LIFETIME_MEDIUM; return CFG_SETTINGS_OK; @@ -932,7 +932,8 @@ int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *cfg, ws_bbr_cfg_t *new_cfg) cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant || cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase || cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase || - cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime) { + cfg->dhcp_address_lifetime != new_cfg->dhcp_address_lifetime || + cfg->rpl_default_lifetime != new_cfg->rpl_default_lifetime) { return CFG_SETTINGS_CHANGED; } @@ -954,7 +955,7 @@ int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, w // cur is optional, default values are for Wi-SUN small network parameters, ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings, new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase, - new_cfg->min_hop_rank_increase); + new_cfg->min_hop_rank_increase, new_cfg->rpl_default_lifetime); ws_bbr_dhcp_address_lifetime_set(cur, new_cfg->dhcp_address_lifetime); } @@ -1210,7 +1211,7 @@ int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_c } if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { - ws_pae_controller_configure(cur, new_cfg, NULL); + ws_pae_controller_configure(cur, new_cfg, NULL, NULL); } if (cfg == new_cfg) { @@ -1230,7 +1231,8 @@ static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg) cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; cfg->sec_prot_trickle_timer_exp = 2; cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; - cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM; + cfg->max_simult_sec_neg_tx_queue_min = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MIN; + cfg->max_simult_sec_neg_tx_queue_max = MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MAX; cfg->initial_key_retry_delay = DEFAULT_INITIAL_KEY_RETRY_TIMER; cfg->initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; @@ -1256,7 +1258,8 @@ int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_c cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax || cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp || cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout || - cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication || + cfg->max_simult_sec_neg_tx_queue_min != new_cfg->max_simult_sec_neg_tx_queue_min || + cfg->max_simult_sec_neg_tx_queue_max != new_cfg->max_simult_sec_neg_tx_queue_max || cfg->initial_key_retry_delay != new_cfg->initial_key_retry_delay || cfg->initial_key_imin != new_cfg->initial_key_retry_delay || cfg->initial_key_imax != new_cfg->initial_key_retry_delay || @@ -1277,7 +1280,7 @@ int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg } if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { - ws_pae_controller_configure(cur, NULL, new_cfg); + ws_pae_controller_configure(cur, NULL, new_cfg, NULL); } if (cfg == new_cfg) { diff --git a/source/6LoWPAN/ws/ws_cfg_settings.h b/source/6LoWPAN/ws/ws_cfg_settings.h index 763d1ff56f..6b5dd98bce 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.h +++ b/source/6LoWPAN/ws/ws_cfg_settings.h @@ -64,6 +64,7 @@ typedef struct ws_bbr_cfg_s { uint16_t dag_max_rank_increase; uint16_t min_hop_rank_increase; uint32_t dhcp_address_lifetime; /**< DHCP address lifetime in seconds minimum 2 hours and maximum as days hours*/ + uint32_t rpl_default_lifetime; /**< RPL default lifetime value minimum from 30 minutes to 16 hours*/ } ws_bbr_cfg_t; /** @@ -114,7 +115,8 @@ typedef struct ws_sec_prot_cfg_s { uint16_t sec_prot_trickle_imin; /**< Security protocol trickle parameters Imin; seconds; default 30 */ uint16_t sec_prot_trickle_imax; /**< Security protocol trickle parameters Imax; seconds; default 90 */ uint8_t sec_prot_trickle_timer_exp; /**< Security protocol trickle timer expirations; default 2 */ - uint16_t sec_max_ongoing_authentication; /**< Pae authenticator max Accept ongoing authentication count */ + uint16_t max_simult_sec_neg_tx_queue_min; /**< PAE authenticator max simultaneous security negotiations TX queue minimum */ + uint16_t max_simult_sec_neg_tx_queue_max; /**< PAE authenticator max simultaneous security negotiations TX queue maximum */ uint16_t initial_key_retry_delay; /**< Delay before starting initial key trickle; seconds; default 120 */ uint16_t initial_key_imin; /**< Initial key trickle Imin; seconds; default 360 */ uint16_t initial_key_imax; /**< Initial key trickle Imax; seconds; default 720 */ diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index bf1bca224f..a11af08d18 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -690,4 +690,14 @@ void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interfac ws_bootstrap_secondary_parent_update(interface); } +void ws_common_border_router_alive_update(protocol_interface_info_entry_t *interface) +{ + if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + return; + } + + // After successful DAO ACK connection to border router is verified + interface->ws_info->pan_timeout_timer = interface->ws_info->cfg->timing.pan_timeout; +} + #endif // HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index c4f92f5381..2761164482 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -173,6 +173,8 @@ void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface); uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size); +void ws_common_border_router_alive_update(protocol_interface_info_entry_t *interface); + #define ws_info(cur) ((cur)->ws_info) #else #define ws_info(cur) ((ws_info_t *) NULL) @@ -189,6 +191,7 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size); #define ws_common_network_size_estimate_get(cur) 0 #define ws_common_primary_parent_update(interface, neighbor) #define ws_common_secondary_parent_update(interface) +#define ws_common_border_router_alive_update(interface) ((void) 0) #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 89a698b3d3..cb400ba302 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -239,6 +239,13 @@ typedef struct ws_bs_ie { #define MPX_KEY_MANAGEMENT_ENC_USER_ID 0x0001 /**< MPX Key management user ID */ #define MPX_LOWPAN_ENC_USER_ID 0xA0ED /**< MPX Lowpan User Id */ +/* + * Wi-SUN MPX MTU size + * + */ + +#define WS_MPX_MAX_MTU 1576 + #define WS_FAN_VERSION_1_0 1 #define WS_NEIGHBOR_LINK_TIMEOUT 2200 @@ -373,4 +380,5 @@ typedef struct ws_bs_ie { #define BR_EAPOL_RELAY_SOCKET_PORT 10255 #define PAE_AUTH_SOCKET_PORT 10254 + #endif /* WS_COMMON_DEFINES_H_ */ diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index f202cfea2f..ce1e1217b0 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -50,6 +50,11 @@ #define WS_RPL_MIN_HOP_RANK_INCREASE 196 #define WS_RPL_MAX_HOP_RANK_INCREASE 2048 +#define WS_RPL_DEFAULT_LIFETIME (3600*2) // 2 hours +#define WS_RPL_DEFAULT_LIFETIME_MEDIUM (3600*4) // 4 hours +#define WS_RPL_DEFAULT_LIFETIME_LARGE (3600*8) // 8 hours +#define WS_RPL_DEFAULT_LIFETIME_XLARGE (3600*12) // 12 hours + #define WS_DHCP_ADDRESS_LIFETIME_SMALL 2*3600 // small networks less than devices 100 #define WS_DHCP_ADDRESS_LIFETIME_MEDIUM 12*3600 // Medium size networks from 100 - 1000 device networks #define WS_DHCP_ADDRESS_LIFETIME_LARGE 24*3600 // Large size networks 1000 + device networks @@ -60,7 +65,7 @@ /* * RPL DAO timeout maximum value. This will force DAO timeout to happen before this time */ -#define WS_RPL_DAO_MAX_TIMOUT (3600*2) +#define WS_RPL_DAO_MAX_TIMOUT (3600*12) /* Border router version change interval * @@ -249,9 +254,8 @@ extern uint8_t DEVICE_MIN_SENS; #define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries // Maximum number of simultaneous security negotiations -#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 20 -#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM 20 -#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 50 +#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MIN 64 +#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MAX 192 /* * Security protocol timer configuration parameters diff --git a/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index 17443e8469..c70f2e36c5 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -68,20 +68,41 @@ int ws_management_network_name_validate( return -1; } -int ws_management_phy_mode_id_set( +int ws_management_domain_configuration_set( int8_t interface_id, - uint8_t phy_mode_id) + uint8_t regulatory_domain, + uint8_t phy_mode_id, + uint8_t channel_plan_id) { + (void)regulatory_domain; (void)interface_id; (void)phy_mode_id; + (void)channel_plan_id; return -1; } -int ws_management_channel_plan_id_set( +int ws_management_domain_configuration_get( int8_t interface_id, + uint8_t *regulatory_domain, + uint8_t *phy_mode_id, + uint8_t *channel_plan_id) +{ + (void)regulatory_domain; + (void)interface_id; + (void)phy_mode_id; + (void)channel_plan_id; + return -1; +} + +int ws_management_domain_configuration_validate( + int8_t interface_id, + uint8_t regulatory_domain, + uint8_t phy_mode_id, uint8_t channel_plan_id) { + (void)regulatory_domain; (void)interface_id; + (void)phy_mode_id; (void)channel_plan_id; return -1; } diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index bdd2aadc9a..b7ff5e7a8d 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -156,12 +156,13 @@ int ws_management_network_name_validate( return 0; } -int ws_management_phy_mode_id_set( +int ws_management_domain_configuration_set( int8_t interface_id, - uint8_t phy_mode_id) + uint8_t regulatory_domain, + uint8_t phy_mode_id, + uint8_t channel_plan_id) { protocol_interface_info_entry_t *cur; - cur = protocol_stack_interface_info_get_by_id(interface_id); if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; @@ -177,10 +178,22 @@ int ws_management_phy_mode_id_set( return -3; } - if (phy_mode_id != 255) { - cfg.phy_mode_id = phy_mode_id; - } else { + if (regulatory_domain == 255) { + cfg.regulatory_domain = cfg_default.regulatory_domain; + } else if (regulatory_domain != 0) { + cfg.regulatory_domain = regulatory_domain; + } + + if (phy_mode_id == 255) { cfg.phy_mode_id = cfg_default.phy_mode_id; + } else if (phy_mode_id != 0) { + cfg.phy_mode_id = phy_mode_id; + } + + if (channel_plan_id == 255) { + cfg.channel_plan_id = cfg_default.channel_plan_id; + } else if (channel_plan_id != 0) { + cfg.channel_plan_id = channel_plan_id; } if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { @@ -190,34 +203,58 @@ int ws_management_phy_mode_id_set( return 0; } -int ws_management_channel_plan_id_set( +int ws_management_domain_configuration_get( int8_t interface_id, - uint8_t channel_plan_id) + uint8_t *regulatory_domain, + uint8_t *phy_mode_id, + uint8_t *channel_plan_id) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_phy_cfg_t cfg; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -2; + } + + if (regulatory_domain) { + *regulatory_domain = cfg.regulatory_domain; + } + if (phy_mode_id) { + *phy_mode_id = cfg.phy_mode_id; + } + if (channel_plan_id) { + *channel_plan_id = cfg.channel_plan_id; + } + + return 0; +} + +int ws_management_domain_configuration_validate( + int8_t interface_id, + uint8_t regulatory_domain, + uint8_t phy_mode_id, + uint8_t channel_plan_id) { protocol_interface_info_entry_t *cur; - cur = protocol_stack_interface_info_get_by_id(interface_id); if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } ws_phy_cfg_t cfg; - ws_phy_cfg_t cfg_default; if (ws_cfg_phy_get(&cfg, NULL) < 0) { return -3; } - if (ws_cfg_phy_default_set(&cfg_default) < 0) { - return -3; - } + cfg.regulatory_domain = regulatory_domain; + cfg.phy_mode_id = phy_mode_id; + cfg.channel_plan_id = channel_plan_id; - if (channel_plan_id != 255) { - cfg.channel_plan_id = channel_plan_id; - } else { - cfg.channel_plan_id = cfg_default.channel_plan_id; - } - - if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { + if (ws_cfg_phy_validate(NULL, &cfg) < 0) { return -4; } diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index 47e73ace70..4e6db848fe 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -66,10 +66,8 @@ #define WAIT_FOR_AUTHENTICATION_TICKS 2 * 60 * 10 // 2 minutes // Wait after authentication has completed before supplicant entry goes inactive #define WAIT_AFTER_AUTHENTICATION_TICKS 15 * 10 // 15 seconds - -/* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how - long to wait for previous negotiation to complete */ -#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds +// Waiting for authentication supplicant list maximum size +#define WAITING_SUPPLICANT_LIST_MAX_SIZE 50 // Default for maximum number of supplicants #define SUPPLICANT_MAX_NUMBER 5000 @@ -93,7 +91,9 @@ typedef struct { ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */ ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */ ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */ + ws_pae_auth_congestion_get *congestion_get; /**< Congestion get callback */ supp_list_t active_supp_list; /**< List of active supplicants */ + supp_list_t waiting_supp_list; /**< List of waiting supplicants */ shared_comp_list_t shared_comp_list; /**< Shared component list */ arm_event_storage_t *timer; /**< Timer */ sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ @@ -101,6 +101,7 @@ typedef struct { sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */ sec_cfg_t *sec_cfg; /**< Security configuration */ uint16_t supp_max_number; /**< Max number of stored supplicants */ + uint16_t waiting_supp_list_size; /**< Waiting supplicants list size */ uint8_t relay_socked_msg_if_instance_id; /**< Relay socket message interface instance identifier */ uint8_t radius_socked_msg_if_instance_id; /**< Radius socket message interface instance identifier */ bool timer_running : 1; /**< Timer is running */ @@ -128,6 +129,7 @@ static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth); static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr); static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address); static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type); +static bool ws_pae_auth_active_limit_reached(uint16_t active_supp, pae_auth_t *pae_auth); static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size); static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result); static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr); @@ -136,6 +138,8 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup 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, uint8_t socked_msg_if_instance_id, supp_entry_t *supp_entry, sec_cfg_t *sec_cfg); static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp); +static void ws_pae_auth_active_supp_deleted(void *pae_auth); +static void ws_pae_auth_waiting_supp_deleted(void *pae_auth); static int8_t tasklet_id = -1; static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link); @@ -159,6 +163,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->pan_id = 0xffff; pae_auth->interface_ptr = interface_ptr; ws_pae_lib_supp_list_init(&pae_auth->active_supp_list); + ws_pae_lib_supp_list_init(&pae_auth->waiting_supp_list); ws_pae_lib_shared_comp_list_init(&pae_auth->shared_comp_list); pae_auth->timer = NULL; @@ -166,12 +171,16 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->nw_key_insert = NULL; pae_auth->nw_keys_remove = NULL; pae_auth->nw_key_index_set = NULL; + pae_auth->nw_info_updated = NULL; + pae_auth->ip_addr_get = NULL; + pae_auth->congestion_get = NULL; pae_auth->next_gtks = next_gtks; pae_auth->certs = certs; pae_auth->sec_keys_nw_info = sec_keys_nw_info; pae_auth->sec_cfg = sec_cfg; pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; + pae_auth->waiting_supp_list_size = 0; pae_auth->gtk_new_inst_req_exp = false; pae_auth->gtk_new_act_time_exp = false; @@ -302,7 +311,7 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } -void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get) +void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get) { if (!interface_ptr) { return; @@ -318,6 +327,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ pae_auth->nw_key_index_set = nw_key_index_set; pae_auth->nw_info_updated = nw_info_updated; pae_auth->ip_addr_get = ip_addr_get; + pae_auth->congestion_get = congestion_get; } void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr) @@ -394,8 +404,11 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p return ret_value; } - // Checks if supplicant is active + // Checks if supplicant is active or waiting supp_entry_t *supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, eui_64); + if (!supp) { + supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->waiting_supp_list, eui_64); + } if (supp) { // Deletes keys and marks as revoked @@ -507,7 +520,8 @@ void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr) /* Purge in maximum five entries from supplicant list (starting from oldest one) per call to the function (called by nanostack monitor) */ - ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE); + ws_pae_lib_supp_list_purge(pae_auth, &pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE, NULL); + ws_pae_lib_supp_list_purge(pae_auth, &pae_auth->waiting_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE, ws_pae_auth_waiting_supp_deleted); } int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated) @@ -608,6 +622,7 @@ static void ws_pae_auth_free(pae_auth_t *pae_auth) ws_pae_lib_shared_comp_list_free(&pae_auth->shared_comp_list); ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list); + ws_pae_lib_supp_list_delete(&pae_auth->waiting_supp_list); kmp_socket_if_unregister(pae_auth->kmp_service); @@ -690,8 +705,9 @@ void ws_pae_auth_fast_timer(uint16_t ticks) } // Updates KMP timers - bool running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->active_supp_list, ticks, kmp_service_timer_if_timeout); - if (!running) { + bool active_running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->active_supp_list, ticks, kmp_service_timer_if_timeout, ws_pae_auth_active_supp_deleted); + bool wait_running = ws_pae_lib_supp_list_timer_update(pae_auth, &pae_auth->waiting_supp_list, ticks, kmp_service_timer_if_timeout, ws_pae_auth_waiting_supp_deleted); + if (!active_running && !wait_running) { ws_pae_auth_timer_stop(pae_auth); } } @@ -936,6 +952,40 @@ static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_ap return ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type); } +static bool ws_pae_auth_active_limit_reached(uint16_t active_supp, pae_auth_t *pae_auth) +{ + return pae_auth->congestion_get(pae_auth->interface_ptr, active_supp); +} + +static supp_entry_t *ws_pae_auth_waiting_supp_list_add(pae_auth_t *pae_auth, supp_entry_t *supp_entry, const kmp_addr_t *addr) +{ + // Entry is already allocated + if (supp_entry) { + ns_list_add_to_start(&pae_auth->waiting_supp_list, supp_entry); + pae_auth->waiting_supp_list_size++; + } else { + // Create a new supplicant entry if not at limit + if (pae_auth->waiting_supp_list_size > WAITING_SUPPLICANT_LIST_MAX_SIZE) { + tr_info("PAE: waiting list full, eui-64: %s", trace_array(addr->eui_64, 8)); + return NULL; + } + supp_entry = ws_pae_lib_supp_list_add(&pae_auth->waiting_supp_list, addr); + if (!supp_entry) { + tr_info("PAE: waiting list no memory, eui-64: %s", trace_array(addr->eui_64, 8)); + return NULL; + } + pae_auth->waiting_supp_list_size++; + sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->sec_keys_nw_info->gtks, pae_auth->certs); + } + + // 90 percent of the EAPOL temporary entry lifetime (10 ticks per second) + supp_entry->waiting_ticks = pae_auth->sec_cfg->timing_cfg.temp_eapol_min_timeout * 900 / 100; + + tr_debug("PAE: to waiting, list size %i, retry %i, eui-64: %s", pae_auth->waiting_supp_list_size, supp_entry->waiting_ticks, trace_array(supp_entry->addr.eui_64, 8)); + + return supp_entry; +} + static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size) { pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); @@ -954,21 +1004,43 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t m supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr)); if (!supp_entry) { - // Checks if active supplicant list has space for new supplicants - if (ws_pae_lib_supp_list_active_limit_reached(&pae_auth->active_supp_list, pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication)) { - tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8)); - return NULL; - } - // Find supplicant from key storage - supp_entry = ws_pae_key_storage_supp_read(pae_auth, kmp_address_eui_64_get(addr), pae_auth->sec_keys_nw_info->gtks, pae_auth->certs); + uint16_t active_supp = ns_list_count(&pae_auth->active_supp_list); + + // Check if supplicant is already on the the waiting supplicant list + supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->waiting_supp_list, kmp_address_eui_64_get(addr)); if (supp_entry) { - // Move supplicant to active list - tr_debug("PAE: to active, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); - ns_list_add_to_start(&pae_auth->active_supp_list, supp_entry); + /* Remove from waiting list (supplicant is later added to active list, or if no room back to the start of the + * waiting list with updated timer) + */ + ns_list_remove(&pae_auth->waiting_supp_list, supp_entry); + pae_auth->waiting_supp_list_size--; + supp_entry->waiting_ticks = 0; + } else { + // Find supplicant from key storage + supp_entry = ws_pae_key_storage_supp_read(pae_auth, kmp_address_eui_64_get(addr), pae_auth->sec_keys_nw_info->gtks, pae_auth->certs); + } + + // Checks if active supplicant list has space for new supplicants + if (ws_pae_auth_active_limit_reached(active_supp, pae_auth)) { + tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8)); + // If there is no space, add supplicant entry to the start of the waiting supplicant list + supp_entry = ws_pae_auth_waiting_supp_list_add(pae_auth, supp_entry, addr); + if (!supp_entry) { + return 0; + } + } else { + if (supp_entry) { + /* + * If there is space and there is already an allocated supplicant, add it to active list and + * start/continue authentication + */ + tr_debug("PAE: to active, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + ns_list_add_to_start(&pae_auth->active_supp_list, supp_entry); + } } } - // If does not exists add it to list + // If supplicant does not exists create a new supplicant entry to the active list if (!supp_entry) { supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr); if (!supp_entry) { @@ -1065,14 +1137,16 @@ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e return; } + // Ensures that supplicant is in active supplicant list before initiating next KMP + if (!ws_pae_lib_supp_list_entry_is_in_list(&pae_auth->active_supp_list, supp_entry)) { + return; + } + ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry); } static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry) { - // Disables KMP retry timer - 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(pae_auth, supp_entry); @@ -1096,21 +1170,6 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup // Increases waiting time for supplicant authentication ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS); - if (next_type == IEEE_802_1X_MKA || next_type == RADIUS_IEEE_802_1X_MKA) { - /* For EAP-TLS, limits the number of ongoing negotiations. If limit - is reached, authenticator does not initiate EAP-TLS right away. - If previous EAP-TLS negotiation completes before negotiation - trigger timeout, authenticator initiates EAP-TLS towards - supplicant. Otherwise supplicant must re-send initial EAPOL-Key - to try again using its trickle schedule */ - uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, next_type); - if (ongoing_eap_tls_cnt >= pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication) { - supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT; - tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8)); - return; - } - } - // Create new instance kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, pae_auth->relay_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg); if (!new_kmp) { @@ -1161,11 +1220,11 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry } else { next_type = IEEE_802_1X_MKA; } - tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + tr_info("PAE: start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); } else if (sec_keys->ptk_mismatch) { // start 4WH towards supplicant next_type = IEEE_802_11_4WH; - tr_info("PAE start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + tr_info("PAE: start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); } int8_t gtk_index = -1; @@ -1191,19 +1250,19 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry // 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)); + 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: 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)); + tr_info("PAE: update GTK index: %i, eui-64: %s", gtk_index, trace_array(supp_entry->addr.eui_64, 8)); } if (next_type == KMP_TYPE_NONE) { - tr_info("PAE authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); + tr_info("PAE: authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); } return next_type; @@ -1254,26 +1313,38 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp) return; } - pae_auth_t *pae_auth = NULL; - supp_entry_t *retry_supp = NULL; - // When EAP-TLS completes check if there are other supplicants that have requested it lately - if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA || kmp_api_type_get(kmp) == RADIUS_IEEE_802_1X_MKA) { - kmp_service_t *service = kmp_api_service_get(kmp); - pae_auth = ws_pae_auth_by_kmp_service_get(service); - if (pae_auth) { - retry_supp = ws_pae_lib_supp_list_entry_retry_timer_get(&pae_auth->active_supp_list); - } - } - // Delete KMP ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp); +} - if (retry_supp) { - tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8)); +static void ws_pae_auth_active_supp_deleted(void *pae_auth_ptr) +{ + pae_auth_t *pae_auth = pae_auth_ptr; + + tr_info("Supplicant deleted"); + + uint16_t active_supp = ns_list_count(&pae_auth->active_supp_list); + if (ws_pae_auth_active_limit_reached(active_supp, pae_auth)) { + return; + } + + supp_entry_t *retry_supp = ns_list_get_first(&pae_auth->waiting_supp_list); + if (retry_supp != NULL) { + ns_list_remove(&pae_auth->waiting_supp_list, retry_supp); + pae_auth->waiting_supp_list_size--; + ns_list_add_to_start(&pae_auth->active_supp_list, retry_supp); + tr_info("PAE: waiting supplicant to active, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8)); + retry_supp->waiting_ticks = 0; ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp); } } +static void ws_pae_auth_waiting_supp_deleted(void *pae_auth_ptr) +{ + pae_auth_t *pae_auth = pae_auth_ptr; + pae_auth->waiting_supp_list_size--; +} + #endif /* HAVE_PAE_AUTH */ #endif /* HAVE_WS */ diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index d302aeaf0f..506ee4ee7b 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -249,6 +249,17 @@ typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interf */ typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address); +/** + * ws_pae_auth_congestion_get get congestion information + * + * \param interface_ptr interface + * \param active_supp active supplicants + * + * \return TRUE reject, FALSE accept + * + */ +typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); + /** * ws_pae_auth_cb_register register PAE authenticator callbacks * @@ -258,9 +269,10 @@ typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ * \param nw_key_index_set network send key index callback * \param nw_info_updated network keys updated callback * \param ip_addr_get IP addressing information callback + * \param congestion_get congestion get callback * */ -void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get); +void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get); #else @@ -268,7 +280,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #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, nw_info_updated, ip_addr_get) {(void) hash_set;} +#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get) {(void) hash_set;} #define ws_pae_auth_start(interface_ptr) #define ws_pae_auth_gtks_updated NULL #define ws_pae_auth_nw_key_index_update NULL diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 57eb9a19c0..da74695ee3 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -88,6 +88,7 @@ typedef struct { ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */ ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */ ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */ + ws_pae_controller_congestion_get *congestion_get; /**< Congestion get callback */ ws_pae_controller_ip_addr_get *ip_addr_get; /**< IP address get callback */ ws_pae_delete *pae_delete; /**< PAE delete callback */ ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */ @@ -117,6 +118,7 @@ static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_key static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr); #ifdef HAVE_PAE_AUTH static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address); +static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); #endif static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr); static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry); @@ -238,7 +240,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit); } - ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get); + ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get, ws_pae_controller_auth_congestion_get); controller->auth_started = true; @@ -247,7 +249,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in return 0; } -int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated) +int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get) { if (!interface_ptr) { return -1; @@ -267,6 +269,7 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ controller->pan_ver_increment = pan_ver_increment; controller->nw_info_updated = nw_info_updated; controller->auth_next_target = auth_next_target; + controller->congestion_get = congestion_get; return 0; } @@ -388,6 +391,20 @@ static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t * controller->ip_addr_get(interface_ptr, address); } + +static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp) +{ + if (!interface_ptr) { + return 0; + } + + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (!controller) { + return 0; + } + + return controller->congestion_get(interface_ptr, active_supp); +} #endif int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid) @@ -472,7 +489,6 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_ 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->sec_keys_nw_info.network_name); continue; @@ -675,6 +691,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) controller->pan_ver_increment = NULL; controller->nw_info_updated = NULL; controller->auth_next_target = NULL; + controller->congestion_get = NULL; memset(&controller->sec_cfg, 0, sizeof(sec_cfg_t)); @@ -685,7 +702,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) return 0; } -int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg) +int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg) { pae_controller_t *controller = ws_pae_controller_get(interface_ptr); if (controller == NULL) { @@ -698,9 +715,6 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt controller->sec_cfg.prot_cfg.sec_prot_trickle_params.k = 0; controller->sec_cfg.prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp; controller->sec_cfg.prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10; - - controller->sec_cfg.prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication; - controller->sec_cfg.prot_cfg.initial_key_retry_delay = sec_prot_cfg->initial_key_retry_delay; controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imin = sec_prot_cfg->initial_key_imin; controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imax = sec_prot_cfg->initial_key_imax; @@ -715,6 +729,10 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt controller->sec_cfg.radius_cfg = pae_controller_config.radius_cfg; + if (timing_cfg) { + controller->sec_cfg.timing_cfg.temp_eapol_min_timeout = timing_cfg->temp_eapol_min_timeout; + } + return 0; } @@ -1232,7 +1250,7 @@ int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t * return 0; } - if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) { + if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL) < 0) { return -1; } @@ -1282,7 +1300,7 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); if (controller) { - ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); + ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL); } return 0; @@ -1335,7 +1353,7 @@ int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, bbr_radius_timin pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); if (controller) { - ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); + ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL); } return 0; diff --git a/source/6LoWPAN/ws/ws_pae_controller.h b/source/6LoWPAN/ws/ws_pae_controller.h index 2b619ccf92..516a6cf22d 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.h +++ b/source/6LoWPAN/ws/ws_pae_controller.h @@ -23,7 +23,7 @@ typedef enum { AUTH_RESULT_OK = 0, // Successful AUTH_RESULT_ERR_NO_MEM = -1, // No memory - AUTH_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received + AUTH_RESULT_ERR_TX_ERR = -2, // TX error (e.g. no acknowledge was received) AUTH_RESULT_ERR_UNSPEC = -3 // Other reason } auth_result_e; @@ -31,6 +31,7 @@ struct nvm_tlv_entry; struct ws_sec_timer_cfg_s; struct ws_sec_prot_cfg_s; struct bbr_radius_timing; +struct ws_timing_cfg_s; /** * ws_pae_controller_set_target sets EAPOL target for PAE supplicant @@ -98,12 +99,13 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr); * \param interface_ptr interface * \param sec_timer_cfg timer configuration or NULL if not set * \param sec_prot_cfg protocol configuration or NULL if not set + * \param timing_cfg timing configuration or NULL if not set * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg); +int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg); /** * ws_pae_controller_init initializes PAE supplicant @@ -612,6 +614,17 @@ typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t */ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name); +/** + * ws_pae_controller_congestion_get get congestion information + * + * \param interface_ptr interface + * \param active_supp active supplicants + * + * \return TRUE reject, FALSE accept + * + */ +typedef bool ws_pae_controller_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); + /** * ws_pae_controller_cb_register register controller callbacks * @@ -625,12 +638,13 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t * * \param nw_frame_counter_read network frame counter read callback * \param pan_ver_increment PAN version increment callback * \param nw_info_updated network information updated callback + * \param congestion_get congestion get callback * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated); +int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get); /** * ws_pae_controller_ip_addr_get gets IP addressing information @@ -701,7 +715,7 @@ void ws_pae_controller_forced_gc(bool full_gc); #define ws_pae_controller_stop(interface_ptr) #define ws_pae_controller_delete(interface_ptr) -#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment) 1 +#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment, congestion_get) 1 #define ws_pae_controller_nvm_tlv_get(interface_ptr) NULL #define ws_pae_controller_forced_gc NULL diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index 3f9ab10b37..fb635e7741 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -193,18 +193,23 @@ supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t entry->addr.type = KMP_ADDR_EUI_64_AND_IP; kmp_address_copy(&entry->addr, addr); - ns_list_add_to_end(supp_list, entry); + ns_list_add_to_start(supp_list, entry); return entry; } -int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *supp) +int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted) { ns_list_remove(supp_list, supp); ws_pae_lib_supp_delete(supp); ns_dyn_mem_free(supp); + + if (supp_deleted != NULL) { + supp_deleted(instance); + } + return 0; } @@ -222,11 +227,11 @@ supp_entry_t *ws_pae_lib_supp_list_entry_eui_64_get(const supp_list_t *supp_list void ws_pae_lib_supp_list_delete(supp_list_t *supp_list) { ns_list_foreach_safe(supp_entry_t, entry, supp_list) { - ws_pae_lib_supp_list_remove(supp_list, entry); + ws_pae_lib_supp_list_remove(NULL, supp_list, entry, NULL); } } -bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout) +bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted) { bool timer_running = false; @@ -235,7 +240,7 @@ bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_ if (running) { timer_running = true; } else { - ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry); + ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry, supp_deleted); } } @@ -260,7 +265,7 @@ void ws_pae_lib_supp_init(supp_entry_t *entry) memset(&entry->addr, 0, sizeof(kmp_addr_t)); memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t)); entry->ticks = 0; - entry->retry_ticks = 0; + entry->waiting_ticks = 0; entry->store_ticks = ws_pae_key_storage_storing_interval_get() * 1000; entry->active = true; entry->access_revoked = false; @@ -283,18 +288,18 @@ bool ws_pae_lib_supp_timer_update(void *instance, supp_entry_t *entry, uint16_t entry->ticks -= ticks; } else { entry->ticks = 0; - entry->retry_ticks = 0; } } // Updates retry timer - if (entry->retry_ticks > ticks) { - entry->retry_ticks -= ticks; + if (entry->waiting_ticks > ticks) { + keep_timer_running = true; + entry->waiting_ticks -= ticks; } else { - if (entry->retry_ticks > 0) { - tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(entry->addr.eui_64, 8)); + if (entry->waiting_ticks > 0) { + tr_info("Waiting supplicant timeout eui-64: %s", trace_array(entry->addr.eui_64, 8)); } - entry->retry_ticks = 0; + entry->waiting_ticks = 0; } if (!instance) { @@ -350,7 +355,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t * entry->addr.type = KMP_ADDR_EUI_64_AND_IP; } -void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry) +void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted) { if (!entry->active) { return; @@ -360,7 +365,7 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l if (entry->access_revoked) { tr_info("Access revoked; deleted, eui-64: %s", trace_array(entry->addr.eui_64, 8)); - ws_pae_lib_supp_list_remove(active_supp_list, entry); + ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted); return; } @@ -368,10 +373,13 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l ws_pae_key_storage_supp_write(instance, entry); // Remove supplicant entry - ws_pae_lib_supp_list_remove(active_supp_list, entry); + ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted); + if (supp_deleted) { + supp_deleted(instance); + } } -void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge) +void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted) { uint16_t active_supp = ns_list_count(active_supp_list); @@ -385,7 +393,7 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) { if (remove_count > 0 && ws_pae_lib_kmp_list_empty(&entry->kmp_list)) { tr_info("Active supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8)); - ws_pae_lib_supp_list_remove(active_supp_list, entry); + ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted); remove_count--; } else { break; @@ -394,16 +402,6 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb } } -bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number) -{ - uint16_t active_supp = ns_list_count(active_supp_list); - if (active_supp > max_number) { - return true; - } - - return false; -} - uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type) { uint16_t kmp_count = 0; @@ -419,6 +417,17 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type) return kmp_count; } +bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry) +{ + ns_list_foreach(supp_entry_t, entry, supp_list) { + if (entry == searched_entry) { + return true; + } + } + + return false; +} + kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size) { ns_list_foreach(supp_entry_t, entry, supp_list) { @@ -432,22 +441,6 @@ kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const return NULL; } -supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list) -{ - supp_entry_t *retry_supp = NULL; - - ns_list_foreach(supp_entry_t, entry, supp_list) { - // Finds entry with shortest timeout i.e. oldest one - if (entry->retry_ticks > 0) { - if (!retry_supp || retry_supp->retry_ticks > entry->retry_ticks) { - retry_supp = entry; - } - } - } - - return retry_supp; -} - int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list) { ns_list_init(comp_list); diff --git a/source/6LoWPAN/ws/ws_pae_lib.h b/source/6LoWPAN/ws/ws_pae_lib.h index dc9a0b67b5..e29ef5bd0f 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.h +++ b/source/6LoWPAN/ws/ws_pae_lib.h @@ -36,7 +36,7 @@ typedef struct supp_entry_s { kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */ sec_prot_keys_t sec_keys; /**< Security keys */ uint32_t ticks; /**< Ticks */ - uint16_t retry_ticks; /**< Retry ticks */ + uint16_t waiting_ticks; /**< Waiting ticks */ uint16_t store_ticks; /**< NVM store ticks */ bool active : 1; /**< Is active */ bool access_revoked : 1; /**< Nodes access is revoked */ @@ -211,16 +211,26 @@ void ws_pae_lib_supp_list_init(supp_list_t *supp_list); */ supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr); +/** + * ws_pae_lib_supp_deleted supplicant delete callback + * + * \param instance Instance + * + */ +typedef void ws_pae_lib_supp_deleted(void *instance); + /** * ws_pae_lib_supp_list_add removes entry from supplicant list * + * \param instance Instance * \param supp_list supplicant list * \param entry entry + * \param supp_deleted callback to call on supplicant delete * * \return < 0 failure * \return >= 0 success */ -int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *entry); +int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted); /** * ws_pae_lib_supp_list_entry_eui_64_get gets entry from supplicant list based on EUI-64 @@ -249,11 +259,12 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list); * \param inactive_supp_list list of inactive supplicants * \param ticks timer ticks * \param timeout callback to call on timeout + * \param supp_deleted callback to call on supplicant delete * * \return true timer needs still to be running * \return false timer can be stopped */ -bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout); +bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted); /** * ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list @@ -336,31 +347,23 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t * * \param instance Instance * \param active_supp_list list of active supplicants * \param entry supplicant entry + * \param supp_deleted callback to call on supplicant delete * */ -void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry); +void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted); /** * ws_pae_lib_supp_list_purge purge inactive supplicants list * + * \param instance Instance * \param active_supp_list list of active supplicants * \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge * to free list entries even when maximum number supplicant entries has not been reached * \param max_purge maximum number of supplicants to purge in one call, 0 means not limited + * \param supp_deleted callback to call on supplicant delete * */ -void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge); - -/** - * ws_pae_lib_supp_list_limit_reached_check check if active supplicant list limit has been reached - * - * \param active_supp_list list of active supplicants - * \param max_number maximum number of supplicant entries - * - * \return true limit has been reached - * \return false limit has not been reached - */ -bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, uint16_t max_number); +void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted); /** * ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants @@ -373,6 +376,17 @@ bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, ui */ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type); +/** + * ws_pae_lib_supp_list_entry_is_in_list checks if the entry is in the list + * + * \param supp_list list of supplicants + * \param searched_entry entry that is searched + * + * \return TRUE entry is in list, FALSE otherwise + * + */ +bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry); + /** * ws_pae_lib_supp_list_kmp_receive_check check if received message is for this KMP in a list of supplicants * @@ -385,16 +399,6 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type) */ kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size); -/** - * ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running - * - * \param supp_list list of supplicants - * - * \return supplicant with retry timer running or NULL if no supplicants with timer running - * - */ -supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list); - /** * ws_pae_lib_shared_comp_list_init init shared component list * diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index d3dc8a0220..c8aeee7267 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -841,7 +841,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds) } auth_result_e result = AUTH_RESULT_ERR_UNSPEC; if (pae_supp->tx_failure_on_initial_key) { - result = AUTH_RESULT_ERR_TX_NO_ACK; + result = AUTH_RESULT_ERR_TX_ERR; pae_supp->tx_failure_on_initial_key = false; } ws_pae_supp_authenticate_response(pae_supp, result); @@ -1254,7 +1254,7 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e /* If initial EAPOL-key message sending fails to tx no acknowledge, indicates failure so that bootstrap can decide if EAPOL target should be changed */ - else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) { + else if (type > IEEE_802_1X_INITIAL_KEY && (result == KMP_RESULT_ERR_TX_NO_ACK || result == KMP_RESULT_ERR_TX_UNSPEC)) { tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8)); /* Fails authentication only if other authentication protocols are not yet started by authenticator */ diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index 8ccf5cb4a8..8ceae7c4c8 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -613,6 +613,16 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) /* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */ if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) { + + if (buffer_data_length(buf) > IPV6_MIN_LINK_MTU) { + /* recover IP addresses that icmpv6_error needs, which routing code will have overwritten */ + buf->src_sa.addr_type = ADDR_IPV6; + memcpy(buf->src_sa.address, buffer_data_pointer(buf) + IPV6_HDROFF_SRC_ADDR, 16); + buf->dst_sa.addr_type = ADDR_IPV6; + memcpy(buf->dst_sa.address, buffer_data_pointer(buf) + IPV6_HDROFF_DST_ADDR, 16); + return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_PACKET_TOO_BIG, 0, IPV6_MIN_LINK_MTU); + } + /* Avoid an infinite loop in the event of routing code failure - never * let them ask for tunnelling more than once. */ @@ -623,6 +633,7 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) buf->options.tunnelled = true; buf->options.ip_extflags = 0; + buf->options.ipv6_use_min_mtu = -1; /* Provide tunnel source, unless already set */ if (buf->src_sa.addr_type == ADDR_NONE) { @@ -1003,7 +1014,7 @@ static buffer_t *ipv6_consider_forwarding_unicast_packet(buffer_t *buf, protocol /* route_info.pmtu will cover limits from both the interface and the * route. As a bonus, it will also cover any PMTUD we happen to have done - * to that destination ourselves, as well as mop up any tunnelling issues. + * to that destination ourselves. Extra limits due to tunnelling are checked on tunnel entry in ipv6_down. */ if (routing->route_info.pmtu < buffer_data_length(buf)) { buf->interface = cur; diff --git a/source/Common_Protocols/ipv6.h b/source/Common_Protocols/ipv6.h index 3a60c224df..0927891c59 100644 --- a/source/Common_Protocols/ipv6.h +++ b/source/Common_Protocols/ipv6.h @@ -57,7 +57,7 @@ typedef enum ipv6_exthdr_stage { * If it needs to insert headers that are not present, it can force insertion * into a tunnel, by: * setting dst_sa and src_sa appropriate for the tunnel endpoints - * XXX does this work out okay with dest cache and PMTU? + * src_sa.addr_type can be set to ADDR_NONE to auto-select tunnel source address * updating route info like next hop if necessary (probably not) * returning IPV6_EXTHDR_MODIFY_TUNNEL * During new header formation for the tunnel, IPV6_EXTHDR_INSERT will be diff --git a/source/Core/include/ns_monitor.h b/source/Core/include/ns_monitor.h index 2d98feb2de..867cff47fc 100644 --- a/source/Core/include/ns_monitor.h +++ b/source/Core/include/ns_monitor.h @@ -33,9 +33,9 @@ int ns_monitor_clear(void); void ns_monitor_timer(uint16_t seconds); -int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical); +int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage); -int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage); +int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage); bool ns_monitor_packet_allocation_allowed(void); diff --git a/source/Core/include/ns_socket.h b/source/Core/include/ns_socket.h index 23ec4db7ec..4af22a4249 100644 --- a/source/Core/include/ns_socket.h +++ b/source/Core/include/ns_socket.h @@ -52,6 +52,10 @@ #define SOCKET_DEFAULT_STREAM_SNDLOWAT 512 #endif +#ifndef SOCKET_DEFAULT_REFERENCE_LIMIT +#define SOCKET_DEFAULT_REFERENCE_LIMIT 512 +#endif + typedef enum socket_family_e { SOCKET_FAMILY_NONE, SOCKET_FAMILY_IPV6, diff --git a/source/Core/ns_monitor.c b/source/Core/ns_monitor.c index 22d4c43e50..83c4d3512c 100644 --- a/source/Core/ns_monitor.c +++ b/source/Core/ns_monitor.c @@ -63,7 +63,7 @@ typedef struct ns_monitor__s { static ns_monitor_t *ns_monitor_ptr = NULL; -static uint8_t ns_dyn_mem_rate_limiting_threshold_percentage = 0; // Percentage of free memory required to allow routing +static ns_mem_heap_size_t ns_dyn_mem_rate_limiting_threshold = 0; // amount of free memory required to allow routing 0 = disabled typedef void (ns_maintenance_gc_cb)(bool full_gc); @@ -176,32 +176,75 @@ int ns_monitor_clear(void) return -1; } -int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical) +int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage) { - if (ns_monitor_ptr && (percentage_critical <= 100) && (percentage_high < percentage_critical)) { + if (ns_monitor_ptr && (critical_percentage <= 100) && (high_percentage < critical_percentage)) { ns_monitor_ptr->heap_high_watermark = SET_WATERMARK( ns_monitor_ptr->mem_stats->heap_sector_size, - percentage_high + high_percentage ); + if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark < high_min) { + ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_min; + } + + if (high_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark > high_max) { + ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_max; + } + ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK( ns_monitor_ptr->mem_stats->heap_sector_size, - percentage_critical + critical_percentage ); - tr_debug("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size); + if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark < critical_min) { + ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_min; + } + + if (critical_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark > critical_max) { + ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_max; + } + + tr_info("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size); return 0; } return -1; } -int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage) +int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage) { - if (free_heap_percentage < 100) { - ns_dyn_mem_rate_limiting_threshold_percentage = free_heap_percentage; + /* To make this function dynamic and useful in larger range of memories the minimum value can be given + * + * example limit(1024, 1) + * 32k RAM Limit = 1024 + * 64k RAM Limit = 1024 + * 128k RAM Limit = 1280 + * 320k RAM Limit = 3200 + */ + if (free_heap_percentage == 0 && minimum_required == 0) { + // Disable rate limiting + ns_dyn_mem_rate_limiting_threshold = 0; return 0; } + if (free_heap_percentage > 100) { + // Sanity check this should not be high at all, but dont want to limit without any good reason + return -1; + } - return -1; + const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat(); + if (ns_dyn_mem_stat && free_heap_percentage) { + ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * free_heap_percentage; + } + + if (ns_dyn_mem_rate_limiting_threshold < minimum_required) { + ns_dyn_mem_rate_limiting_threshold = minimum_required; + } + + if (Maximum_allowed && ns_dyn_mem_rate_limiting_threshold > Maximum_allowed) { + ns_dyn_mem_rate_limiting_threshold = Maximum_allowed; + } + tr_info("Monitor rate limit incoming packets at:%lu", (unsigned long)ns_dyn_mem_rate_limiting_threshold); + + return 0; } bool ns_monitor_packet_allocation_allowed(void) @@ -212,8 +255,8 @@ bool ns_monitor_packet_allocation_allowed(void) const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat(); - if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold_percentage) { - if (ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_stat->heap_sector_size / 100 * (100 - ns_dyn_mem_rate_limiting_threshold_percentage)) { + if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold) { + if (ns_dyn_mem_stat->heap_sector_size - ns_dyn_mem_stat->heap_sector_allocated_bytes < ns_dyn_mem_rate_limiting_threshold) { // Packet allocation not allowed as memory is running low. return false; } diff --git a/source/Core/ns_socket.c b/source/Core/ns_socket.c index bd919a99af..7bd2e5e30d 100644 --- a/source/Core/ns_socket.c +++ b/source/Core/ns_socket.c @@ -45,6 +45,8 @@ #define RANDOM_PORT_NUMBER_COUNT (RANDOM_PORT_NUMBER_END - RANDOM_PORT_NUMBER_START + 1) #define RANDOM_PORT_NUMBER_MAX_STEP 500 +static bool socket_reference_limit(socket_t *socket_ptr); + static uint16_t port_counter; static socket_t *socket_instance[SOCKETS_MAX]; @@ -113,6 +115,7 @@ socket_t *socket_pointer_get(int8_t socket) static void socket_data_event_push(buffer_t *buf) { + buf->socket = socket_reference(buf->socket); arm_event_s event = { .receiver = socket_event_handler, .sender = 0, @@ -137,6 +140,7 @@ bool socket_data_queued_event_push(socket_t *socket) }; if (eventOS_event_send(&event) != 0) { + socket_dereference(socket); return false; } return true; @@ -167,12 +171,8 @@ static void socket_cb_event_run(const socket_cb_event_t *event) } } -void socket_buffer_cb_run(socket_t *socket, buffer_t *buffer) +static void socket_buffer_cb_run(socket_t *socket, buffer_t *buffer) { - if (socket->id == -1 || !socket->u.live.fptr) { - buffer_free(buffer); - return; - } eventOS_scheduler_set_active_tasklet(socket->tasklet); @@ -222,9 +222,19 @@ void socket_tasklet_event_handler(arm_event_s *event) } case ARM_SOCKET_DATA_CB: { buffer_t *buf = event->data_ptr; - /* Reference the socket here*/ - socket_t *socket = socket_reference(buf->socket); - if (socket->flags & SOCKET_BUFFER_CB) { + + if (!buf || !buf->socket) { + tr_error("Socket CB: Buf or Socket pointer NULL"); + buffer_free(buf); + break; + } + + socket_t *socket = buf->socket; + + if (socket->id == -1 || !socket->u.live.fptr) { + //Socket is released Free just Buffer + buffer_free(buf); + } else if (socket->flags & SOCKET_BUFFER_CB) { // They just take ownership of the buffer. No read calls. socket_buffer_cb_run(socket, buf); } else { @@ -243,7 +253,9 @@ void socket_tasklet_event_handler(arm_event_s *event) } case ARM_SOCKET_DATA_QUEUED_CB: { socket_t *socket = event->data_ptr; - socket_cb_run(socket); + if (socket) { + socket_cb_run(socket); + } socket_dereference(socket); break; } @@ -454,6 +466,14 @@ socket_t *socket_allocate(socket_type_t type) return socket; } +static bool socket_reference_limit(socket_t *socket_ptr) +{ + if (socket_ptr && socket_ptr->refcount < SOCKET_DEFAULT_REFERENCE_LIMIT) { + return false; + } + return true; +} + /* Increase reference counter on socket, returning now-owned pointer */ socket_t *socket_reference(socket_t *socket_ptr) { @@ -479,7 +499,7 @@ socket_t *socket_dereference(socket_t *socket_ptr) } if (socket_ptr->refcount == 0) { - tr_error("ref underflow"); + tr_error("Socket %d ref underflow", socket_ptr->id); return NULL; } if (--socket_ptr->refcount == 0) { @@ -870,6 +890,13 @@ socket_error_t socket_up(buffer_t *buf) goto drop; } + //Limit here + if (socket_reference_limit(socket)) { + tr_error("Socket reference limit drop RX %u", socket->refcount); + goto drop; + } + + if (socket->rcvq.data_byte_limit == 0) { // Old-style one event per buffer socket_data_event_push(buf); @@ -1113,6 +1140,12 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr // Everything below this point is non-TCP #endif //NO_TCP + if (socket_reference_limit(socket_ptr)) { + tr_error("Socket reference limit drop TX %u", socket_ptr->refcount); + ret_val = -1; + goto fail; + } + /** * Mark Socket id to buffer meta data */ diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index 8784c634d2..7443f30507 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -93,7 +93,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r //Validate Client DUID dhcp_link_options_params_t clientDUID; if (libdhcpv6_get_link_address_from_duid(replyPacket->clientDUID.duid, replyPacket->clientDUID.duid_length, replyPacket->clientDUID.type, &clientDUID) == 0) { - dhcp_allocated_address = libdhcpv6_address_allocated_list_scan(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew); + dhcp_allocated_address = libdhcpv6_address_allocate(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew); } if (dhcp_allocated_address) { address_allocated = true; @@ -109,7 +109,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) { address_allocated = false; - libdhcpv6_address_rm_from_allocated_list(serverBase, dhcp_allocated_address->nonTemporalAddress); + libdhcpv6_address_delete(serverBase, dhcp_allocated_address->nonTemporalAddress); } } } @@ -299,9 +299,9 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { //Delete Server data base if (serverInfo->removeCb) { - uint8_t allocated_address[16]; - libdhcpv6_allocated_address_write(allocated_address, cur, serverInfo); - serverInfo->removeCb(interface, allocated_address, NULL); + uint8_t ipAddress[16]; + libdhcpv6_allocated_address_write(ipAddress, cur, serverInfo); + serverInfo->removeCb(interface, ipAddress, NULL); } } @@ -327,12 +327,19 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 8], /* Control GUA address for client by DUI.Default value is true * + * Anonymous and disable address list can optimize either + * Using 16 bit suffix to optimize data amount in network + * and having list of assigned addresses meaning larger RAM usage at border router + * + * or Using SLAAC type address generation and not have a list of addresses at Border router + * -> Less RAM usage, but more bandwidth used * * /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 mode true assign addresses anonymously. false define address by Prefix + client id + * /param disable_address_list Dont keep track of assigned Addresses (Can't be used if anonymous) */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) +int DHCPv6_server_service_set_address_generation_anonymous(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool disable_address_list) { dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); if (!serverInfo) { @@ -340,12 +347,13 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu } - serverInfo->enableAddressAutonous = mode; + serverInfo->anonymousAddress = mode; if (mode) { - serverInfo->disableAddressListAllocation = autonomous_skip_list; + serverInfo->disableAddressList = disable_address_list; } else { - serverInfo->disableAddressListAllocation = false; + serverInfo->disableAddressList = false; } + tr_info("DHCPv6 %s, address list %s", mode ? "anonymous address" : "address mode SLAAC", disable_address_list ? "Not Stored" : "Stored"); return 0; } @@ -375,6 +383,7 @@ int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static if (!serverInfo) { return -1; } + tr_info("DHCPv6 duid %s", trace_array(duid_ptr, duid_length)); return libdhcpv6_server_duid_set(serverInfo, duid_ptr, duid_type, duid_length); } @@ -399,6 +408,7 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ } serverInfo->maxSupportedClients = maxClientCount; + tr_info("DHCPv6 maximum clients %"PRIu32, serverInfo->maxSupportedClients); return 0; } @@ -421,6 +431,7 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu return -1; } serverInfo->validLifetime = validLifeTimne; + tr_info("DHCPv6 Valid lifetime %"PRIu32, serverInfo->validLifetime); return 0; } @@ -510,7 +521,7 @@ 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, bool autonomous_skip_list) +int DHCPv6_server_service_set_address_generation_anonymous(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list) { (void) interface; (void) guaPrefix; diff --git a/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 024a46acde..5a9fb86949 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/source/DHCPv6_Server/DHCPv6_server_service.h @@ -62,13 +62,19 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); /* Control GUA address for client by DUI.Default value is true * + * Anonymous and disable address list can optimize either + * Using 16 bit suffix to optimize data amount in network + * and having list of assigned addresses meaning larger RAM usage at border router + * + * or Using SLAAC type address generation and not have a list of addresses at Border router + * -> Less RAM usage, but more bandwidth used * * /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 + * /param mode true assign addresses anonymously. false define address by Prefix + client id + * /param disable_address_list Dont keep track of assigned Addresses (Can't be used if anonymous) */ -int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode, bool autonomous_skip_list); +int DHCPv6_server_service_set_address_generation_anonymous(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/MAC/IEEE802_15_4/mac_data_buffer.h b/source/MAC/IEEE802_15_4/mac_data_buffer.h index e01ee3a040..3e5a7629ab 100644 --- a/source/MAC/IEEE802_15_4/mac_data_buffer.h +++ b/source/MAC/IEEE802_15_4/mac_data_buffer.h @@ -91,6 +91,8 @@ typedef struct mac_pre_build_frame { uint8_t csma_periods_left; uint8_t fhss_retry_count; uint8_t fhss_cca_retry_count; + uint8_t stored_retry_cnt; + uint8_t stored_cca_cnt; uint16_t initial_tx_channel; uint32_t tx_time; bool upper_layer_request: 1; @@ -102,6 +104,7 @@ typedef struct mac_pre_build_frame { bool WaitResponse: 1; unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes unsigned priority: 2; + unsigned stored_priority: 2; struct mac_pre_build_frame *next; //Pointer for queue purpose } mac_pre_build_frame_t; diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 84e2612fcf..3012e5c056 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -42,7 +42,8 @@ typedef enum mac_event_t { MAC_TX_TIMEOUT, MAC_ACK_SECURITY_FAIL, MAC_UNKNOWN_DESTINATION, - MAC_TX_PRECOND_FAIL + MAC_TX_PRECOND_FAIL, + MAC_RETURN_TO_QUEUE } mac_event_t; typedef enum mac_tx_status_type_t { diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 899813b724..40b0319e89 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1507,11 +1507,16 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, mcps_data_conf_t confirm; 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 (!mcps_buffer_edfe_data_failure(rf_ptr, buffer) && ((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), rf_ptr->mac_tx_start_channel) == true) { - + if (!mcps_buffer_edfe_data_failure(rf_ptr, buffer) && ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL) || (rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE))) { + if ((rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE) || 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; + } else if (rf_ptr->mac_tx_result == MAC_RETURN_TO_QUEUE) { + buffer->stored_retry_cnt = rf_ptr->mac_tx_retry; + buffer->stored_cca_cnt = rf_ptr->mac_cca_retry; + buffer->stored_priority = buffer->priority; + // Use priority to transmit it first when proper channel is available + buffer->priority = MAC_PD_DATA_TX_IMMEDIATELY; } else { buffer->fhss_retry_count += rf_ptr->mac_tx_status.retry; } @@ -2135,8 +2140,16 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma rf_ptr->macTxRequestAck = false; memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t)); - rf_ptr->mac_cca_retry = 0; - rf_ptr->mac_tx_retry = 0; + if (buffer->priority == MAC_PD_DATA_TX_IMMEDIATELY) { + // Return original priority and retry/CCA counts + buffer->priority = buffer->stored_priority; + rf_ptr->mac_tx_retry = rf_ptr->mac_tx_status.retry = buffer->stored_retry_cnt; + rf_ptr->mac_cca_retry = rf_ptr->mac_tx_status.cca_cnt = buffer->stored_cca_cnt; + buffer->stored_retry_cnt = buffer->stored_cca_cnt = 0; + } else { + rf_ptr->mac_tx_retry = 0; + rf_ptr->mac_cca_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) { diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.h b/source/MAC/IEEE802_15_4/mac_mcps_sap.h index 3992ae3125..8368f4eac2 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.h +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.h @@ -49,6 +49,7 @@ typedef enum { #define MAC_PD_DATA_NORMAL_PRIORITY 0 //Normal MCPS DATA REQ #define MAC_PD_DATA_MEDIUM_PRIORITY 1 //Indirect Data which is polled #define MAC_PD_DATA_HIGH_PRIOTITY 2 //Beacon request Beacon response +#define MAC_PD_DATA_TX_IMMEDIATELY 3 //Only for packets whose transmission was interrupted by wrong channel type. E.g. unicast on broadcast channel. #define MCPS_SAP_DATA_IND_EVENT 1 #define MCPS_SAP_DATA_CNF_EVENT 2 diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 766901c82c..08a5604237 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -189,6 +189,9 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup) length = tx_buf->len; } if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) { +#ifdef TIMING_TOOL_TRACES + tr_info("%u CSMA_start", mac_mcps_sap_get_phy_timestamp(rf_mac_setup)); +#endif return 0; } @@ -451,9 +454,13 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r return -1; } +#ifdef TIMING_TOOL_TRACES + if ((status == PHY_LINK_CCA_FAIL) || (status == PHY_LINK_CCA_PREPARE)) { + tr_info("%u CSMA_done", mac_mcps_sap_get_phy_timestamp(rf_ptr)); + } +#endif + if (status == PHY_LINK_CCA_PREPARE) { - - if (rf_ptr->mac_ack_tx_active || rf_ptr->mac_edfe_tx_active) { goto VALIDATE_TX_TIME; } @@ -485,10 +492,12 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r mac_sap_cca_fail_cb(rf_ptr, 0xffff); return PHY_TX_NOT_ALLOWED; } - // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back - // to queue by using CCA fail event + // When FHSS TX handle returns -3, we are trying to: + // - transmit broadcast packet on unicast channel + // - transmit unicast packet on broadcast channel + // Push back to queue to allow sending applicable packet if (tx_handle_retval == -3) { - mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + mac_tx_done_state_set(rf_ptr, MAC_RETURN_TO_QUEUE); return PHY_TX_NOT_ALLOWED; } else if (tx_handle_retval == -2) { mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION); @@ -505,6 +514,9 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r active_buf->csma_periods_left--; active_buf->tx_time += rf_ptr->multi_cca_interval; mac_pd_sap_set_phy_tx_time(rf_ptr, active_buf->tx_time, true); +#ifdef TIMING_TOOL_TRACES + tr_info("%u CSMA_start", mac_mcps_sap_get_phy_timestamp(rf_ptr)); +#endif return PHY_RESTART_CSMA; } } diff --git a/source/MPL/mpl.c b/source/MPL/mpl.c index 68c56b95c1..1ab5b21cf1 100644 --- a/source/MPL/mpl.c +++ b/source/MPL/mpl.c @@ -1065,6 +1065,7 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i if (!domain) { // We will need to tunnel - do nothing on the inner packet *result = 0; + buf->options.ipv6_use_min_mtu = 1; return buf; } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index af80b13f78..7c51210cee 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -452,6 +452,9 @@ rpl_domain_t *rpl_control_create_domain(void) ns_list_init(&domain->instances); domain->non_storing_downstream_interface = -1; domain->callback = NULL; + domain->new_parent_add = NULL; + domain->parent_dis = NULL; + domain->prefix_cb = NULL; domain->cb_handle = NULL; domain->force_leaf = false; domain->process_routes = true; @@ -528,12 +531,13 @@ void rpl_control_free_domain_instances_from_interface(protocol_interface_info_en } } -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, rpl_parent_dis_callback_t parent_dis, void *cb_handle) { domain->callback = callback; domain->prefix_cb = prefix_learn_cb; domain->cb_handle = cb_handle; domain->new_parent_add = new_parent_add; + domain->parent_dis = parent_dis; } /* To do - this should live somewhere nicer. Basically a bootstrap @@ -562,6 +566,11 @@ bool rpl_control_have_dodag(rpl_domain_t *domain) typedef void rpl_control_predicate_loop_fn_t(rpl_instance_t *instance, rpl_dodag_version_t *version, void *arg); +typedef struct rpl_loopfn_trigger_unicast_dio_arg { + struct protocol_interface_info_entry *interface; + const uint8_t *dst; +} rpl_loopfn_trigger_unicast_dio_arg_t; + /* Callbacks for rpl_control_predicate_loop */ static void rpl_loopfn_reset_dio_timer(rpl_instance_t *instance, rpl_dodag_version_t *dodag_version, void *handle) @@ -570,12 +579,19 @@ static void rpl_loopfn_reset_dio_timer(rpl_instance_t *instance, rpl_dodag_versi (void)handle; rpl_instance_inconsistency(instance); -} + //Check was Multicast DIS from parent + rpl_loopfn_trigger_unicast_dio_arg_t *arg = handle; + rpl_domain_t *domain = arg->interface->rpl_domain; + if (domain && domain->parent_dis) { -typedef struct rpl_loopfn_trigger_unicast_dio_arg { - struct protocol_interface_info_entry *interface; - const uint8_t *dst; -} rpl_loopfn_trigger_unicast_dio_arg_t; + if (rpl_instance_address_is_parent(instance, arg->dst)) { + // Call Multicast DIS parent Callback + domain->parent_dis(arg->dst, arg->interface, instance); + } + } + + +} static void rpl_loopfn_trigger_unicast_dio(rpl_instance_t *instance, rpl_dodag_version_t *dodag_version, void *handle) { diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index e1525eee81..e0cd4ef09f 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -45,6 +45,8 @@ typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, 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 void rpl_parent_dis_callback_t(const uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance); + typedef struct rpl_route_info { uint8_t node[8]; /* IID of parent in parent child relation table */ uint8_t parent[8]; /* IID of child in parent child relation table */ @@ -65,6 +67,7 @@ typedef struct rpl_domain { rpl_domain_callback_t *callback; rpl_prefix_callback_t *prefix_cb; rpl_new_parent_callback_t *new_parent_add; + rpl_parent_dis_callback_t *parent_dis; void *cb_handle; } rpl_domain_t; @@ -159,7 +162,7 @@ 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, rpl_parent_dis_callback_t parent_dis, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); diff --git a/source/RPL/rpl_data.c b/source/RPL/rpl_data.c index c718f34c43..099192a107 100644 --- a/source/RPL/rpl_data.c +++ b/source/RPL/rpl_data.c @@ -46,6 +46,7 @@ #include "RPL/rpl_structures.h" #include "RPL/rpl_policy.h" #include "RPL/rpl_data.h" +#include "6LoWPAN/ws/ws_common.h" #define TRACE_GROUP "RPLa" @@ -373,6 +374,7 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i case IPV6_EXTHDR_INSERT: { if (!destination_in_instance) { /* We don't add a header - we'll do it on the tunnel */ + buf->options.ipv6_use_min_mtu = 1; *result = 0; return buf; } @@ -964,6 +966,7 @@ static buffer_t *rpl_data_exthdr_provider_srh(buffer_t *buf, ipv6_exthdr_stage_t if (!buf->options.tunnelled) { if (stage == IPV6_EXTHDR_SIZE || stage == IPV6_EXTHDR_INSERT) { *result = 0; + buf->options.ipv6_use_min_mtu = 1; return buf; } } @@ -1054,6 +1057,11 @@ drop: buf->options.ip_extflags |= IPEXT_SRH_RPL; + if (ws_info(cur)) { + //Call SRC route header handler hook to Wi-SUN refresh border router alive + ws_common_border_router_alive_update(cur); + } + uint16_t hlen = (ptr[1] + 1) * 8; uint8_t segs_left = ptr[3]; diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 9dc69c6c38..496313a08a 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1602,6 +1602,45 @@ void rpl_instance_remove_interface(rpl_instance_t *instance, int8_t if_id) } } +static bool rpl_instance_parent_selected(rpl_instance_t *instance) +{ + if (rpl_instance_am_root(instance)) { + return true; + } + + // We don't have DAO target generated + if (ns_list_count(&instance->dao_targets) == 0) { + return false; + } + + // We don't have any valid parent selected + if (!rpl_instance_parent_selection_ready(instance)) { + return false; + } + + return true; +} + +static bool rpl_instance_dao_route_registered(rpl_instance_t *instance) +{ + if (rpl_instance_am_root(instance)) { + //Border router is allways at stable state + return true; + } + + /* Address registrations for parent ongoing*/ + if (rpl_policy_parent_confirmation_requested() && instance->pending_neighbour_confirmation) { + return false; + } + + /* 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 false; + } + + return true; +} + /* Trigger DIO transmission - all interfaces multicast if addr+cur are NULL, else unicast */ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_entry_t *cur, const uint8_t *addr) { @@ -1638,6 +1677,13 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_ rpl_dodag_conf_t *conf; if (addr) { conf = &dodag->config; + //Unicast + if (rank != RPL_RANK_INFINITE) { + if (!rpl_instance_parent_selected(instance)) { + tr_debug("parent selection not ready. DIO rank INFINITE"); + rank = RPL_RANK_INFINITE; + } + } } else if (dodag->new_config_advertisment_count < rpl_policy_dio_multicast_config_advertisment_min_count()) { conf = &dodag->config; if (dodag->new_config_advertisment_count < 0xfe) { @@ -1649,6 +1695,10 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_ rpl_control_transmit_dio(instance->domain, cur, instance->id, dodag_version->number, rank, dodag->g_mop_prf, instance->dtsn, dodag, dodag->id, conf, addr); + if (addr) { + return; + } + dodag_version->last_advertised_rank = rank; /* When we advertise a new lowest rank, need to re-evaluate our rank limits */ @@ -1728,8 +1778,10 @@ void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair) instance->repair_dis_count = 0; } else { instance->repair_dis_timer = 0; - instance->advertised_dodag_membership_since_last_repair = false; + } + //SET False allways for guarantee reboot possibility + instance->advertised_dodag_membership_since_last_repair = false; /* When repair ends, eliminate all higher-rank neighbours (potential sub-DODAG) from table */ if (!repair && instance->current_dodag_version) { @@ -1855,21 +1907,12 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) /* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */ if (!rpl_instance_am_root(instance) && !instance->poison_count && !instance->advertised_dodag_membership_since_last_repair && rpl_policy_parent_confirmation_requested()) { - // We don't have DAO target generated - if (ns_list_count(&instance->dao_targets) == 0) { + //Validate Parent is selected and registered + if (!rpl_instance_parent_selected(instance)) { return; } - - // We don't have any valid parent selected - if (!rpl_instance_parent_selection_ready(instance)) { - 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) { + //Verify that DAO is registered + if (!rpl_instance_dao_route_registered(instance)) { return; } } diff --git a/source/Security/kmp/kmp_api.h b/source/Security/kmp/kmp_api.h index fa945eb480..2dea6d6333 100644 --- a/source/Security/kmp/kmp_api.h +++ b/source/Security/kmp/kmp_api.h @@ -49,8 +49,8 @@ typedef enum { typedef enum { KMP_RESULT_OK = 0, // Successful KMP_RESULT_ERR_NO_MEM = -1, // No memory - KMP_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received - KMP_RESULT_ERR_UNSPEC = -3 // Other reason + KMP_RESULT_ERR_TX_NO_ACK = -2, // No TX acknowledge was received + KMP_RESULT_ERR_TX_UNSPEC = -3 // Other TX reason } kmp_result_e; typedef enum { 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 ec3600e84c..6467839c46 100644 --- a/source/Security/protocols/key_sec_prot/key_sec_prot.c +++ b/source/Security/protocols/key_sec_prot/key_sec_prot.c @@ -324,7 +324,7 @@ static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e 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, SEC_RESULT_ERR_UNSPEC); + sec_prot_result_set(&data->common, SEC_RESULT_ERR_TX_UNSPEC); } prot->state_machine_call(prot); return 0; diff --git a/source/Security/protocols/sec_prot.h b/source/Security/protocols/sec_prot.h index 565ad5148a..cf7aa54101 100644 --- a/source/Security/protocols/sec_prot.h +++ b/source/Security/protocols/sec_prot.h @@ -31,7 +31,7 @@ typedef enum { SEC_RESULT_OK = 0, SEC_RESULT_ERR_NO_MEM = -1, SEC_RESULT_ERR_TX_NO_ACK = -2, - SEC_RESULT_ERR_UNSPEC = -3, + SEC_RESULT_ERR_TX_UNSPEC = -3, SEC_RESULT_TIMEOUT = -4, SEC_RESULT_ERROR = -5, SEC_RESULT_CONF_ERROR = -6, diff --git a/source/Security/protocols/sec_prot_cfg.h b/source/Security/protocols/sec_prot_cfg.h index dd75e2c226..17efc2b589 100644 --- a/source/Security/protocols/sec_prot_cfg.h +++ b/source/Security/protocols/sec_prot_cfg.h @@ -23,10 +23,11 @@ typedef struct sec_prot_cfg_s { trickle_params_t sec_prot_trickle_params; uint16_t sec_prot_retry_timeout; - uint16_t sec_max_ongoing_authentication; uint16_t initial_key_retry_delay; trickle_params_t initial_key_trickle_params; uint8_t initial_key_retry_cnt; + uint8_t max_ongoing_auth_constant; + uint16_t max_ongoing_auth_size_scaler; } sec_prot_cfg_t; /* Security timer configuration settings */ @@ -53,9 +54,14 @@ typedef struct sec_radius_cfg_s { bool radius_addr_set : 1; /**< Radius server address is set */ } sec_radius_cfg_t; +typedef struct sec_timing_cfg_s { + uint16_t temp_eapol_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 330 */ +} sec_timing_cfg_t; + typedef struct sec_cfg_s { sec_prot_cfg_t prot_cfg; sec_timer_cfg_t timer_cfg; + sec_timing_cfg_t timing_cfg; sec_radius_cfg_t *radius_cfg; } sec_cfg_t; diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 9377967e3d..de2a3385ec 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -348,7 +348,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) } if (fhss_structure->ws->is_on_bc_channel == false) { - fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); + fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - ((int64_t) delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); fhss_structure->ws->is_on_bc_channel = true; next_channel = fhss_structure->ws->bc_channel = fhss_ws_calc_bc_channel(fhss_structure); @@ -621,7 +621,7 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a } // Do not allow unicast destination on broadcast channel if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) { - return -1; + return -3; } // Check TX/RX slot if (!fhss_ws_check_tx_allowed(fhss_structure)) { diff --git a/source/Service_Libs/utils/ns_conf.c b/source/Service_Libs/utils/ns_conf.c index b2e0f26d15..affc32cc8b 100644 --- a/source/Service_Libs/utils/ns_conf.c +++ b/source/Service_Libs/utils/ns_conf.c @@ -24,10 +24,10 @@ int ns_conf_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical) { - return ns_monitor_heap_gc_threshold_set(percentage_high, percentage_critical); + return ns_monitor_heap_gc_threshold_set(0, 0, percentage_high, 0, 0, percentage_critical); } int ns_conf_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage) { - return ns_monitor_packet_ingress_rate_limit_by_memory(free_heap_percentage); + return ns_monitor_packet_ingress_rate_limit_by_memory(0, 0, free_heap_percentage); } diff --git a/source/ipv6_stack/ipv6_routing_table.c b/source/ipv6_stack/ipv6_routing_table.c index 711159c4d5..e253f0b36f 100644 --- a/source/ipv6_stack/ipv6_routing_table.c +++ b/source/ipv6_stack/ipv6_routing_table.c @@ -1195,17 +1195,6 @@ static const bool ipv6_route_probing[ROUTE_MAX] = { [ROUTE_RPL_INSTANCE] = true, }; -/* Which route types get minimum link MTU by default */ -/* Makes life easier for tunnel-based systems like RPL */ -static const bool ipv6_route_min_mtu[ROUTE_MAX] = { - [ROUTE_RPL_DAO] = true, - [ROUTE_RPL_DAO_SR] = true, - [ROUTE_RPL_DIO] = true, - [ROUTE_RPL_ROOT] = true, - [ROUTE_RPL_INSTANCE] = true, - [ROUTE_MPL] = true, -}; - // Remember when a route source has deleted an entry - allows buffers still in // event queue to have their route info invalidated. static bool ipv6_route_source_invalidated[ROUTE_MAX]; @@ -1647,7 +1636,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i route->info.info = info; route->info.source_id = source_id; route->info.interface_id = interface_id; - route->info.pmtu = ipv6_route_min_mtu[source] ? IPV6_MIN_LINK_MTU : 0xFFFF; + route->info.pmtu = 0xFFFF; if (next_hop) { route->on_link = false; memcpy(route->info.next_hop_addr, next_hop, 16); diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index d324c81269..858d2f0931 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -31,6 +31,8 @@ #ifdef HAVE_DHCPV6_SERVER +#define TRACE_GROUP "dhcp" + static NS_LARGE NS_LIST_DEFINE(dhcpv6_gua_server_list, dhcpv6_gua_server_entry_s, link); bool libdhcpv6_gua_server_list_empty(void) @@ -49,10 +51,9 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) } entry->serverDynamic_DUID = server_duid_ptr; entry->serverDynamic_DUID_length = 16; - entry->firstFreedId = 0; entry->firstUnusedId = DHCP_ADDRESS_ID_START; - entry->enableAddressAutonous = true; - entry->disableAddressListAllocation = false; + entry->anonymousAddress = false; + entry->disableAddressList = false; entry->maxSupportedClients = 200; entry->validLifetime = 7200; entry->removeCb = NULL; @@ -63,47 +64,34 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) return entry; } -static uint16_t libdhcpv6_get_next_freed_id(dhcpv6_gua_server_entry_s *serverInfo) +static uint16_t libdhcpv6_get_unique_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) { + uint8_t suggested_id = serverInfo->firstUnusedId; - 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 Current freedID this will update after this call to new one - last_allocated_id = cur->allocatedID; - continue; + do { + ns_list_foreach(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + if (serverInfo->firstUnusedId == cur->allocatedID) { + serverInfo->firstUnusedId++; + if (serverInfo->firstUnusedId == 0) { + serverInfo->firstUnusedId++; + } + //Start from beginning + break; } - } 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; + } while (suggested_id != serverInfo->firstUnusedId); + //return the first free and increase the value for the next time. + serverInfo->firstUnusedId = suggested_id + 1; + return suggested_id; } 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; + // Unique IDs start to generate from 1 and continue to go up every new address + // if we go around 65535 we start from 1 and search for free id + + return libdhcpv6_get_unique_id(serverInfo); } static void libdhcpv6_gen_suffics_from_eui48(uint8_t *ptr, uint8_t *eui48) @@ -124,93 +112,12 @@ static void libdhcpv6_gen_suffics_from_allocated_id(uint8_t *ptr, uint8_t *serve 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; - memcpy(ptr, serverInfo->guaPrefix, 8); - ptr += 8; - if (serverInfo->enableAddressAutonous) { - if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || - entry->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { - memcpy(ptr, entry->linkId, 8); - *ptr ^= 2; - return 0; - } - - 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) +static void libdhcpv6_address_list_entry_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; - } - } - //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; - -} - - void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) { //Check All allocated server inside this loop @@ -223,9 +130,9 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) //Stop use this address for leasequery and delete Route or address map address->preferredLifetime = 0; if (cur->removeCb) { - uint8_t allocated_address[16]; - libdhcpv6_allocated_address_write(allocated_address, address, cur); - cur->removeCb(cur->interfaceId, allocated_address, cur->guaPrefix); + uint8_t ipAddress[16]; + libdhcpv6_allocated_address_write(ipAddress, address, cur); + cur->removeCb(cur->interfaceId, ipAddress, cur->guaPrefix); } } else { address->preferredLifetime -= timeUpdateInSeconds; @@ -233,7 +140,7 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) } if (address->lifetime <= timeUpdateInSeconds) { - libdhcpv6_address_free(cur, address); + libdhcpv6_address_list_entry_free(cur, address); } else { address->lifetime -= timeUpdateInSeconds; } @@ -337,8 +244,7 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t if (serverInfo) { if ((serverInfo->interfaceId == interfaceId) && (memcmp(serverInfo->guaPrefix, prefix, 8) == 0)) { ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { - ns_list_remove(&serverInfo->allocatedAddressList, cur); - ns_dyn_mem_free(cur); + libdhcpv6_address_list_entry_free(serverInfo, cur); } ns_list_foreach_safe(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) { @@ -372,7 +278,28 @@ static void libdhcpv6_address_entry_lifetime_set(dhcpv6_allocated_address_entry_ } } -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) +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->anonymousAddress) { + //Generate from 16-bit allocate and default suffic's + libdhcpv6_gen_suffics_from_allocated_id(ptr, serverInfo->clientIdDefaultSuffics, address->allocatedID); + return; + } + //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; + } +} + +static void libdhcpv6_generate_address_entry(dhcpv6_allocated_address_t *address, dhcpv6_allocated_address_entry_t *cur, dhcpv6_gua_server_entry_s *serverInfo) { libdhcpv6_allocated_address_write(address->nonTemporalAddress, cur, serverInfo); memcpy(address->linkId, cur->linkId, 8); @@ -384,61 +311,14 @@ static void libdhcpv6_copy_allocated_entry_to_temp(dhcpv6_allocated_address_entr 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) +static void libdhcpv6_address_list_entry_add_to_list(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_entry_t *allocated) { - 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) -{ - 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; -} - -void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) -{ - 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; - } - } -} - - -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) { + if (allocated->allocatedID != 0) { + // If we have allocated ID we sort by it if it is 0 we dont do any sorting 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); - } + ns_list_add_before(&serverInfo->allocatedAddressList, cur, allocated); return; } } @@ -446,68 +326,87 @@ static void libdhcpv6_address_id_add_to_list(dhcpv6_gua_server_entry_s *serverIn 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) +void libdhcpv6_address_delete(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) { - dhcpv6_allocated_address_t *newEntry = NULL; - dhcpv6_allocated_address_entry_t *allocatedEntry = NULL; + uint8_t device_address[16]; + if (memcmp(serverInfo->guaPrefix, address, 8)) { + return; + } + + ns_list_foreach_safe(dhcpv6_allocated_address_entry_t, cur, &serverInfo->allocatedAddressList) { + libdhcpv6_allocated_address_write(device_address, cur, serverInfo); + if (memcmp(address, device_address, 16) == 0) { + libdhcpv6_address_list_entry_free(serverInfo, cur); + return; + } + } +} + +static dhcpv6_allocated_address_entry_t *libdhcpv6_address_list_entry_create(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_allocated_address_entry_t *source) +{ + dhcpv6_allocated_address_entry_t *entry; + + entry = ns_dyn_mem_alloc(sizeof(dhcpv6_allocated_address_entry_t)); + + if (!entry) { + return NULL; + } + + *entry = *source; + libdhcpv6_address_list_entry_add_to_list(serverInfo, entry); + return entry; +} + + +dhcpv6_allocated_address_t *libdhcpv6_address_allocate(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_entry_t newEntry; uint16_t duiLength = 6; if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE || linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) { duiLength = 8; } - if (serverInfo->enableAddressAutonous && serverInfo->disableAddressListAllocation) { - //Accept allways when autonous - newEntry = &serverInfo->tempAddressEntry; - allocateNew = false; - } - + // Search if we have old address in list 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; - libdhcpv6_address_entry_lifetime_set(cur, serverInfo->validLifetime); - libdhcpv6_copy_allocated_entry_to_temp(cur, &serverInfo->tempAddressEntry, serverInfo); - return &serverInfo->tempAddressEntry; - } + if (cur->linkType == linkType && memcmp(cur->linkId, linkId, duiLength) == 0) { + cur->iaID = iaID; + cur->T0 = T0; + cur->T1 = T1; + libdhcpv6_address_entry_lifetime_set(cur, serverInfo->validLifetime); + libdhcpv6_generate_address_entry(&serverInfo->tempAddressEntry, cur, serverInfo); + return &serverInfo->tempAddressEntry; } } - if (allocateNew) { - 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); - } - } + if (!allocateNew) { + return NULL; } - return newEntry; + if (ns_list_count(&serverInfo->allocatedAddressList) >= serverInfo->maxSupportedClients) { + // Maximum supported clients reached + return NULL; + } + + // Generate new address + memcpy(newEntry.linkId, linkId, duiLength); + newEntry.linkType = linkType; + newEntry.iaID = iaID; + newEntry.T0 = T0; + newEntry.T1 = T1; + newEntry.allocatedID = 0; + libdhcpv6_address_entry_lifetime_set(&newEntry, serverInfo->validLifetime); + if (serverInfo->anonymousAddress) { + // Generate anonymous address id + newEntry.allocatedID = libdhcpv6_address_id_allocate(serverInfo); + } + + if (!serverInfo->disableAddressList) { + // Create new List item and add to list + libdhcpv6_address_list_entry_create(serverInfo, &newEntry); + } + + libdhcpv6_generate_address_entry(&serverInfo->tempAddressEntry, &newEntry, serverInfo); + return &serverInfo->tempAddressEntry; } dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) diff --git a/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index 3ea3e5f2ab..4dab618b92 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/source/libDHCPv6/libDHCPv6_server.h @@ -59,7 +59,6 @@ typedef struct dhcpv6_vendor_data_s { ns_list_link_t link; /*!< List link entry */ } dhcpv6_vendor_data_t; - typedef struct dhcpv6_allocated_address_s { uint8_t nonTemporalAddress[16]; uint8_t linkId[8]; /*!< Services UL64 */ @@ -71,6 +70,7 @@ typedef struct dhcpv6_allocated_address_s { uint32_t lifetime; } dhcpv6_allocated_address_t; + typedef NS_LIST_HEAD(dhcpv6_allocated_address_entry_t, link) dhcpv6_allocated_address_list_t; typedef NS_LIST_HEAD(dhcpv6_dns_server_data_t, link) dhcpv6_dns_server_list_t; typedef NS_LIST_HEAD(dhcpv6_vendor_data_t, link) dhcpv6_vendor_data_list_t; @@ -85,14 +85,13 @@ 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: 1; - bool disableAddressListAllocation: 1; + bool anonymousAddress: 1; + bool disableAddressList: 1; uint16_t socketInstance_id; uint8_t guaPrefix[8]; uint8_t serverDynamic_DUID_length; 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; @@ -111,12 +110,11 @@ dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length); 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_allocated_address_t *libdhcpv6_address_get_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); +void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo); +void libdhcpv6_address_delete(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_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); +dhcpv6_allocated_address_t *libdhcpv6_address_allocate(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); dhcpv6_dns_server_data_t *libdhcpv6_dns_server_allocate(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); dhcpv6_vendor_data_t *libdhcpv6_vendor_data_discover(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number); @@ -127,15 +125,23 @@ uint8_t *libdhcpv6_dns_server_message_writes(dhcpv6_gua_server_entry_s *serverIn uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr); #else #define libdhcpv6_gua_server_list_empty() true -#define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL -#define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance, prefixPtr) NULL #define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType) NULL -#define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) ((void)0) -#define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) ((void)0) -#define libdhcpv6_gua_server_free_by_interfaceid(interfaceId) ((void)0) -#define libdhcpv6_address_get_from_allocated_list(serverInfo, address) NULL -#define libdhcpv6_address_rm_from_allocated_list(serverInfo, address) ((void)0) -#define libdhcpv6_address_allocated_list_scan( serverInfo, linkId, linkType, iaID, T0, T1, allocateNew) NULL +#define libdhcpv6_server_duid_set(server_info, duid_ptr, duid_type, duid_length) +#define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) +#define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) +#define libdhcpv6_allocated_address_write(ptr, address, serverInfo) +#define libdhcpv6_address_delete(serverInfo, address) +#define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL +#define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance,prefixPtr) NULL +#define libdhcpv6_address_allocate(serverInfo, euid64, linkType, iaID, T0, T1, allocateNew) NULL +#define libdhcpv6_dns_server_discover(serverInfo, address) NULL +#define libdhcpv6_dns_server_allocate(serverInfo, address) NULL +#define libdhcpv6_vendor_data_discover(serverInfo, enterprise_number) NULL +#define libdhcpv6_vendor_data_allocate(serverInfo, enterprise_number) NULL +#define libdhcpv6_dns_server_message_sizes(serverInfo) 0 +#define libdhcpv6_vendor_data_message_sizes(serverInfo) 0 +#define libdhcpv6_dns_server_message_writes(serverInfo, ptr) NULL +#define libdhcpv6_vendor_data_message_writes(serverInfo, ptr) NULL #endif #endif /* LIBDHCPV6_SERVER_H_ */