Merge pull request #11156 from artokin/nanostack_patch_for_mbed_os_5_13_x

Nanostack patch release for Mbed OS 5.13.x
pull/11104/head
Seppo Takalo 2019-08-06 11:28:36 +03:00 committed by GitHub
commit 13ee14c624
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 2029 additions and 773 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -192,14 +192,16 @@ static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_
coap_transaction_t *this = NULL;
(void)param;
if (!resp_ptr || !address_ptr) {
return -1;
}
tr_warn("transaction was not handled %d", resp_ptr->msg_id);
if (resp_ptr->coap_status == COAP_STATUS_BUILDER_BLOCK_SENDING_DONE) {
return 0;
}
tr_warn("transaction was not handled %d", resp_ptr->msg_id);
if (!resp_ptr || !address_ptr) {
return -1;
}
if (resp_ptr->token_ptr) {
this = transaction_find_client_by_token(resp_ptr->token_ptr, resp_ptr->token_len, address_ptr->addr_ptr, address_ptr->port);
}

View File

@ -65,6 +65,7 @@ $(TESTDIRS):
$(CLEANTESTDIRS):
@make -C $(@:clean-%=%) clean
@rm -fr results
.PHONY: release
release:

View File

@ -183,6 +183,12 @@ typedef struct fhss_statistics {
/** FHSS synchronization lost counter. */
uint32_t fhss_synch_lost;
/** FHSS TX to unknown neighbour counter. */
uint32_t fhss_unknown_neighbor;
/** FHSS channel retry counter. */
uint32_t fhss_channel_retry;
} fhss_statistics_t;
/**

View File

@ -76,6 +76,14 @@ extern int ns_fhss_ws_configuration_set(const fhss_api_t *fhss_api, const fhss_w
*/
extern int ns_fhss_delete(fhss_api_t *fhss_api);
/**
* @brief Starts collecting FHSS statistics.
* @param fhss_api FHSS instance.
* @param fhss_statistics Pointer to stored statistics.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_statistics_start(const fhss_api_t *fhss_api, fhss_statistics_t *fhss_statistics);
#ifdef __cplusplus
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_CONF_H_
#define _NS_CONF_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file ns_conf.h
* \brief Nanostack configuration API.
*/
/**
* \brief Set threshold for memory garbage collection.
*
* Nanostack heap usage is monitored in regular intervals. If too much memory has been used then garbage collection (GC)
* is triggered. GC has two adjustable thresholds: HIGH and CRITICAL. HIGH threshold is lower one and once exceeded
* a GC will try to release memory that is used for caching. When CRITTICAL threshold is exceeded them GC will try to release
* memory more aggressiveliy.
*
* Nanostack memory monitoring can only work if memory statistics are enabled in nsdynmemLIB.
*
* \param percentage_high Percentage of total heap when garbage collection is first time triggered
* \param percentage_critical Percentage of total heap when critical garbage collection is triggered
*
* \return 0 in success, negative value in case of error.
*
*/
int ns_conf_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical);
/**
* \brief Limit amount of incoming packets if system does not have enough free memory.
* Memory statistics must been initialized in nsdynmemLIB to get this feature working.
*
* \param free_heap_percentage Percentage of free heap that must be available when packet arrives to MAC layer.
* \return 0 in case of success, <0 otherwise.
*/
int ns_conf_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage);
#ifdef __cplusplus
}
#endif
#endif /* _NS_CONF_H_ */

View File

@ -18,6 +18,10 @@
#ifndef _NS_FILE_SYSTEM_H_
#define _NS_FILE_SYSTEM_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file ns_file_system.h
* \brief Nanostack file system API.
@ -35,9 +39,7 @@
* \return 0 in success, negative value in case of error.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
int ns_file_system_set_root_path(const char *root_path);
/**
@ -47,6 +49,7 @@ int ns_file_system_set_root_path(const char *root_path);
*
*/
char *ns_file_system_get_root_path(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* Copyright (c) 2016-2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -81,6 +81,13 @@ extern struct fhss_api *ns_sw_mac_get_fhss_api(struct mac_api_s *mac_api);
*/
extern int ns_sw_mac_statistics_start(struct mac_api_s *mac_api, struct mac_statistics_s *mac_statistics);
/**
* @brief Read current timestamp.
* @param mac_api MAC instance.
* @return Current timestamp in us
*/
extern uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api);
#ifdef __cplusplus
}
#endif

View File

@ -77,6 +77,7 @@ extern "C" {
#define NETWORK_SIZE_AUTOMATIC 0x00
#define NETWORK_SIZE_SMALL 0x01
#define NETWORK_SIZE_MEDIUM 0x08
#define NETWORK_SIZE_LARGE 0x10
@ -85,6 +86,16 @@ extern "C" {
*/
#define WS_MANAGEMENT_API_VER_2
/**
* \brief Struct ws_statistics defines the Wi-SUN statistics storage structure.
*/
typedef struct ws_statistics {
/** Asynch TX counter */
uint32_t asynch_tx_count;
/** Asynch RX counter */
uint32_t asynch_rx_count;
} ws_statistics_t;
/**
* Initialize Wi-SUN stack.
*
@ -255,6 +266,30 @@ int ws_management_fhss_broadcast_channel_function_configure(
uint8_t dwell_interval,
uint32_t broadcast_interval);
/**
* Start collecting Wi-SUN statistics.
*
* \param interface_id Network interface ID.
* \param stats_ptr Pointer to stored statistics.
*
* \return 0 Success.
* \return <0 Failure.
*/
int ws_statistics_start(
int8_t interface_id,
ws_statistics_t *stats_ptr);
/**
* Stop collecting Wi-SUN statistics.
*
* \param interface_id Network interface ID.
*
* \return 0 Success.
* \return <0 Failure.
*/
int ws_statistics_stop(
int8_t interface_id);
#ifdef __cplusplus
}
#endif

View File

@ -1605,7 +1605,7 @@ static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entr
protocol_6lowpan_release_short_link_address_from_neighcache(cur_interface, entry_ptr->mac16);
protocol_6lowpan_release_long_link_address_from_neighcache(cur_interface, entry_ptr->mac64);
}
mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index);
mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index, entry_ptr->mac64);
//Removes ETX neighbor
etx_neighbor_remove(cur_interface->id, entry_ptr->index);
//Remove MLE frame counter info

View File

@ -866,7 +866,7 @@ int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr)
return 0;
}
void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index)
void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index, uint8_t *mac64)
{
if (!mac_api) {
return;
@ -880,7 +880,7 @@ void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index)
set_req.attr_index = attribute_index;
set_req.value_pointer = (void *)&device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("unRegister Device");
tr_debug("Unregister Device %u, mac64: %s", attribute_index, trace_array(mac64, 8));
mac_api->mlme_req(mac_api, MLME_SET, &set_req);
}
@ -910,7 +910,7 @@ void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_desc, pro
set_req.attr_index = attribute_index;
set_req.value_pointer = (void *)device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("Register Device");
tr_debug("Register Device %u, mac16 %x mac64: %s, %"PRIu32, attribute_index, device_desc->ShortAddress, trace_array(device_desc->ExtAddress, 8), device_desc->FrameCounter);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
}

View File

@ -115,7 +115,7 @@ int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr
int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr);
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index);
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index, uint8_t *mac64);
void mac_helper_device_description_write(struct protocol_interface_info_entry *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt);

View File

@ -855,8 +855,14 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac
*/
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh), ADDR_802_15_4_LONG);
if (entry && !entry->ffd_device) {
rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime);
if (entry) {
if (ws_info(cur_interface)) {
ws_common_etx_validate(cur_interface, entry);
}
if (!entry->ffd_device) {
rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime);
}
}
protocol_6lowpan_neighbor_address_state_synch(cur_interface, aro->eui64, neigh->ip_address + 8);

View File

@ -2015,7 +2015,7 @@ void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mac_neigh
thread_routing_remove_link(cur, neighbour->mac16);
thread_router_bootstrap_reset_child_info(cur, neighbour);
protocol_6lowpan_release_long_link_address_from_neighcache(cur, neighbour->mac64);
mac_helper_devicetable_remove(cur->mac_api, neighbour->index);
mac_helper_devicetable_remove(cur->mac_api, neighbour->index, neighbour->mac64);
thread_neighbor_class_entry_remove(&cur->thread_info->neighbor_class, neighbour->index);
}

View File

@ -40,25 +40,31 @@
#include "ws_bbr_api.h"
#define TRACE_GROUP "wsbs"
#define TRACE_GROUP "BBRw"
#define RPL_INSTANCE_ID 1
#ifdef HAVE_WS_BORDER_ROUTER
#define WS_ULA_LIFETIME 24*3600
#define WS_ROUTE_LIFETIME WS_ULA_LIFETIME
#define WS_DHCP_ADDRESS_LIFETIME 2*3600
#define BBR_CHECK_INTERVAL 60
#define BBR_BACKUP_ULA_DELAY 300
/* when creating BBR make ULA dodag ID always and when network becomes available add prefix to DHCP
*
*
*/
static int8_t backbone_interface_id = -1; // BBR backbone information
static uint16_t configuration = BBR_ULA_C | BBR_GUA_C | BBR_GUA_ROUTE;
static uint16_t configuration = 0;
static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
static uint8_t static_ula_address[16] = {0};
static uint8_t static_dodag_id[16] = {0};
static uint8_t global_dodag_id[16] = {0};
static uint32_t bbr_delay_timer = 20; // initial delay.
static uint8_t current_dodag_id[16] = {0};
static uint8_t current_local_prefix[8] = {0};
static uint8_t current_global_prefix[8] = {0};
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
static rpl_dodag_conf_t rpl_conf = {
// Lifetime values
@ -68,7 +74,7 @@ static rpl_dodag_conf_t rpl_conf = {
.authentication = 0,
.path_control_size = 7,
.dag_max_rank_increase = 2048,
.min_hop_rank_increase = 256,
.min_hop_rank_increase = 196,
// DIO configuration
.dio_interval_min = WS_RPL_DIO_IMIN,
.dio_interval_doublings = WS_RPL_DIO_DOUBLING,
@ -115,31 +121,20 @@ static void ws_bbr_rpl_root_start(uint8_t *dodag_id)
}
// RPL memory limits set larger for Border router
rpl_control_set_memory_limits(64 * 1024, 0);
// Save configured static id to check for changes later
memcpy(static_dodag_id, dodag_id, 16);
}
static void ws_bbr_rpl_root_stop(void)
{
tr_info("RPL root stop");
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
protocol_6lowpan_rpl_root_dodag = NULL;
memset(static_ula_address, 0, 16);
memset(static_dodag_id, 0, 16);
memset(global_dodag_id, 0, 16);
if (protocol_6lowpan_rpl_root_dodag) {
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
protocol_6lowpan_rpl_root_dodag = NULL;
}
memset(current_local_prefix, 0, 8);
memset(current_global_prefix, 0, 8);
memset(current_dodag_id, 0, 16);
}
static void ws_bbr_ula_prefix_enable(uint8_t *dodag_id)
{
tr_info("RPL ula prefix start");
uint8_t t_flags = PIO_A;
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, t_flags, 7200, 7200, false);
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, 0x18, 7200, false);
}
static int ws_border_router_proxy_validate(int8_t interface_id, uint8_t *address)
{
@ -163,29 +158,24 @@ int ws_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handl
return -1;
}
if (status) {
tr_debug("Border router Backhaul link ready");
} else {
tr_debug("Border router Backhaul link down");
}
tr_debug("Border router Backhaul link %s", status ? "ready" : "down");
return 0;
}
static int ws_bbr_static_ula_create(protocol_interface_info_entry_t *cur)
static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
{
if (memcmp(static_ula_address, ADDR_UNSPECIFIED, 16) != 0) {
if (memcmp(current_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
// address generated
return 0;
}
tr_info("BBR generate ula prefix");
// This address is only used if no other address available.
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, static_dodag_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
if (!add_entry) {
tr_err("dodagid create failed");
return -1;
}
memcpy(static_ula_address, add_entry->address, 16);
tr_info("BBR generate ula prefix addr %s", trace_ipv6(static_ula_address));
memcpy(current_dodag_id, add_entry->address, 16);
tr_info("BBR generate DODAGID %s", trace_ipv6(current_dodag_id));
addr_policy_table_add_entry(static_dodag_prefix, 64, 2, WS_NON_PREFFRED_LABEL);
return 0;
@ -195,61 +185,53 @@ static int ws_bbr_static_ula_create(protocol_interface_info_entry_t *cur)
* 0 static non rooted self generated own address
* 1 static address with backbone connectivity
*/
static int ws_bbr_static_dodag_get(protocol_interface_info_entry_t *cur, uint8_t *dodag_id_ptr)
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) {
// static configuration for ethernet available
ns_list_foreach(if_address_entry_t, add_entry, &cur->ip_addresses) {
if (memcmp(add_entry->address, bb_interface->ipv6_configure->static_prefix64, 8) == 0) {
//tr_info("BBR static config available");
if (dodag_id_ptr) {
memcpy(dodag_id_ptr, add_entry->address, 16);
}
return 1;
}
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);
}
}
ws_bbr_static_ula_create(cur);
// only own generated prefix available
if (dodag_id_ptr) {
memcpy(dodag_id_ptr, static_ula_address, 16);
}
return 0;
return;
}
static int ws_bbr_dodag_get(protocol_interface_info_entry_t *cur, uint8_t *static_dodag_id_ptr, uint8_t *dodag_id_ptr)
static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_ptr)
{
uint8_t global_address[16];
if (static_dodag_id_ptr) {
memset(static_dodag_id_ptr, 0, 16);
}
memset(global_prefix_ptr, 0, 8);
if (dodag_id_ptr) {
memset(dodag_id_ptr, 0, 16);
}
if (ws_bbr_static_dodag_get(cur, static_dodag_id_ptr) < 0) {
// no static configuration available
return -1;
}
// By default static dodagID prefix is used as local prefix
memcpy(local_prefix_ptr, current_dodag_id, 8);
ws_bbr_bb_static_prefix_get(local_prefix_ptr);
if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
// No global prefix available
return 0;
return;
}
if (memcmp(global_address, dodag_id_ptr, 8) == 0) {
// static address is same
return 0;
protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
if_address_entry_t *addr_entry = addr_get_entry(bb_interface, global_address);
if (!addr_entry || addr_entry->preferred_lifetime == 0) {
return;
}
memcpy(dodag_id_ptr, global_address, 16);
return 0;
//tr_debug("BBR address %s lifetime %d pref %d", trace_ipv6(addr_entry->address), addr_entry->valid_lifetime, addr_entry->preferred_lifetime);
if (memcmp(global_address, local_prefix_ptr, 8) == 0) {
// static prefix is same
return;
}
memcpy(global_prefix_ptr, global_address, 8);
return;
}
static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
{
@ -284,7 +266,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
memcpy(&ll[8], cur->mac, 8);
ll[8] ^= 2;
tr_debug("DHCP server activate %s", trace_ipv6(global_id));
tr_debug("DHCP server activate %s", trace_ipv6_prefix(global_id, 64));
if (DHCPv6_server_service_init(cur->id, global_id, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) != 0) {
tr_error("DHCPv6 Server create fail");
@ -293,7 +275,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true);
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, 7200);
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, WS_DHCP_ADDRESS_LIFETIME);
ws_dhcp_client_address_request(cur, global_id, ll);
}
@ -307,86 +289,136 @@ static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_
static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
{
uint8_t static_id[16] = {0};
uint8_t global_id[16] = {0};
uint8_t local_prefix[8] = {0};
uint8_t global_prefix[8] = {0};
//tr_info("BBR status check");
ws_bbr_dodag_get(cur, static_id, global_id);
// Check if we need to wait for Global ID
if (configuration & BBR_GUA_WAIT) {
if (memcmp(global_dodag_id, ADDR_UNSPECIFIED, 16) == 0 &&
memcmp(global_id, ADDR_UNSPECIFIED, 16) == 0) {
// We need to wait for Global connectivity to start anything
return;
/*
* Start RPL Root
*/
if (!protocol_6lowpan_rpl_root_dodag) {
// Generate DODAGID
if (ws_bbr_static_dodagid_create(cur) == 0) {
ws_bbr_rpl_root_start(current_dodag_id);
}
}
if (memcmp(static_dodag_id, static_id, 16) != 0) {
// Static id updated or first setup
ws_bbr_rpl_root_start(static_id);
if (configuration & BBR_ULA_C) {
// Start static ULA prefix and routing always
ws_bbr_ula_prefix_enable(static_id);
if (!protocol_6lowpan_rpl_root_dodag) {
// Failed to start
tr_info("BBR failed to start");
return;
}
/*
* Check that DODAGID is still valid
*/
if (protocol_interface_address_compare(current_dodag_id) != 0) {
//DODAGID is lost need to restart
tr_err("DODAGID lost restart RPL");
memset(current_dodag_id, 0, 16);
ws_bbr_rpl_root_stop();
return;
}
ws_bbr_dodag_get(local_prefix, global_prefix);
tr_debug("BBR global %s, local %s", trace_ipv6_prefix(global_prefix, 64), trace_ipv6_prefix(local_prefix, 64));
/*
* Add default route to RPL
*/
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, WS_ROUTE_LIFETIME, false);
/*
* Create static ULA configuration or modify if needed
*/
if ((configuration & BBR_ULA_C) &&
memcmp(current_local_prefix, local_prefix, 8) != 0) {
// Generate Static ULA
// Start static ULA prefix and routing always
if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
// Remove Old ULA prefix
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_local_prefix, 64, PIO_A, 0, 0, true);
}
if (memcmp(local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
tr_info("RPL Local prefix activate %s", trace_ipv6_prefix(local_prefix, 64));
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, local_prefix, 64, PIO_A, WS_ULA_LIFETIME, WS_ULA_LIFETIME, false);
memcpy(current_local_prefix, local_prefix, 8);
}
}
if (memcmp(global_dodag_id, global_id, 16) != 0) {
/*
* Check if backup ULA prefix is needed
*/
if (memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
//Global prefix not available count if backup ULA should be created
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 (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
tr_info("start using backup prefix %s", trace_ipv6_prefix(local_prefix, 64));
}
memcpy(global_prefix, local_prefix, 8);
}
} else {
//Global connection OK
global_prefix_unavailable_timer = 0;
}
/*
* Check for Global prefix
*/
if (memcmp(current_global_prefix, global_prefix, 8) != 0) {
// Global prefix changed
if (memcmp(global_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
// TODO remove old global prefix
tr_info("RPL GUA deactivate %s", trace_ipv6(global_dodag_id));
tr_info("RPL global prefix deactivate %s", trace_ipv6_prefix(current_global_prefix, 64));
// Old backbone information is deleted after 120 seconds
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 0, true);
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 0, 0, true);
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 0, true);
ipv6_route_add_with_info(global_dodag_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0);
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, 0, true);
if (configuration & BBR_GUA_ROUTE) {
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, true);
}
ipv6_route_add_with_info(current_global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0);
ws_bbr_dhcp_server_stop(cur, global_dodag_id);
ws_bbr_dhcp_server_stop(cur, current_global_prefix);
}
// TODO add global prefix
if (memcmp(global_id, ADDR_UNSPECIFIED, 16) != 0) {
//DHCPv6 Server flags set 0 by default
uint8_t t_flags = 0;
if (memcmp(global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
tr_info("RPL global prefix activate %s", trace_ipv6_prefix(global_prefix, 64));
// Add default route to RPL
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 7200, false);
// Enable default routing to backbone
ipv6_route_add_with_info(global_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0);
if (configuration & BBR_GUA_SLAAC) {
// GUA prefix is using SLAAC so no DHCP started and set correct flags for prefix
t_flags = PIO_A;
icmpv6_slaac_address_add(cur, global_id, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
} else {
ws_bbr_dhcp_server_start(cur, global_id);
if (ipv6_route_add_with_info(global_prefix, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0) == NULL) {
tr_err("global route add failed");
return;
}
ws_bbr_dhcp_server_start(cur, global_prefix);
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false);
// no check for failure should have
if (configuration & BBR_GUA_C) {
// Add also global prefix and route to RPL
uint32_t valid_lifetime;
if (t_flags & PIO_A) {
valid_lifetime = 7200;
} else {
valid_lifetime = 0;
}
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_id, 64, t_flags, valid_lifetime, valid_lifetime, false);
}
if (configuration & BBR_GUA_ROUTE) {
// Add also global prefix and route to RPL
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, false);
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
}
}
memcpy(global_dodag_id, global_id, 16);
memcpy(current_global_prefix, global_prefix, 8);
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
nd_proxy_downstream_interface_register(cur->id, ws_border_router_proxy_validate, ws_border_router_proxy_state_update);
}
} else if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
/*
* This is a keep alive validation RPL is updated to hold the real info.
* There is no status checks on prefix adds so this makes sure they are not lost
* DHCP validation should be done also
*/
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, 0, false);
if (configuration & BBR_GUA_ROUTE) {
// Add also global prefix and route to RPL
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
}
}
}
void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
@ -408,7 +440,7 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
if (bbr_delay_timer > seconds) {
bbr_delay_timer -= seconds;
} else {
bbr_delay_timer = 20; // 20 second interval between status checks
bbr_delay_timer = BBR_CHECK_INTERVAL; // 20 second interval between status checks
// prequisists
// Wi-SUN network configuration started without RPL
@ -425,16 +457,6 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
// 2. if GUA prefix becomes available in backend add new prefix to DODAG
// 3. if GUA prefix is removed remove the prefix.
if (protocol_6lowpan_rpl_root_dodag) {
// Border router is active
if (0 != protocol_interface_address_compare(static_dodag_id)) {
// Dodag has become invalid need to delete
tr_info("RPL static dodag not valid anymore %s", trace_ipv6(static_dodag_id));
ws_bbr_rpl_root_stop();
} else {
}
}
ws_bbr_rpl_status_check(cur);
}
@ -445,7 +467,7 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
} else {
// Border router has timed out
tr_debug("Border router version number update");
cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME;
cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config);
cur->ws_info->pan_information.pan_version++;
// Inconsistent for border router to make information distribute faster
ws_bootstrap_configuration_trickle_reset(cur);
@ -455,8 +477,8 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
}
// We update the RPL version in same time to allow nodes to reselect parent
// As configuration is made so that devices cant move downward in dodag this allows it
// TODO think the correct rate for this
if (cur->ws_info->pan_information.pan_version && cur->ws_info->pan_information.pan_version % RPL_VERSION_LIFETIME / PAN_VERSION_LIFETIME == 0) {
// Version number update is only done if DoDAG MAX Rank Increase parameter is 0
if (rpl_conf.dag_max_rank_increase == 0 && cur->ws_info->pan_information.pan_version && cur->ws_info->pan_information.pan_version % RPL_VERSION_LIFETIME / cur->ws_info->pan_version_timer == 0) {
// Third the rate of configuration version change at default 5 hours
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
}
@ -476,13 +498,12 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
}
//
const uint8_t *prefix_ptr;
if ((configuration & (BBR_ULA_C | BBR_GUA_C)) == BBR_GUA_C) {
//Use just GUA Prefix
prefix_ptr = global_dodag_id;
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) != 0) {
//Use GUA Prefix
prefix_ptr = current_global_prefix;
} else {
//Use ULA for indentifier
prefix_ptr = static_dodag_id;
prefix_ptr = current_local_prefix;
}
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, prefix_ptr, &result);
@ -598,3 +619,4 @@ int ws_bbr_node_access_revoke_start(int8_t interface_id)
return -1;
#endif
}

View File

@ -53,6 +53,7 @@
#include "6LoWPAN/ws/ws_llc.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
#include "6LoWPAN/ws/ws_ie_lib.h"
#include "6LoWPAN/ws/ws_stats.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
@ -80,7 +81,7 @@ static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur);
static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data);
static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new);
static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast);
static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur);
static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur);
static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur);
@ -90,10 +91,12 @@ static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_
static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot);
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter);
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter);
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success);
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);
static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
typedef enum {
WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/
@ -101,6 +104,13 @@ typedef enum {
WS_EAPOL_PARENT_SYNCH, /**< Broadcast synch with EAPOL parent*/
} ws_parent_synch_e;
static void ws_bootsrap_create_ll_address(uint8_t *ll_address, const uint8_t *mac64)
{
memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_address + 8, mac64, 8);
ll_address[8] ^= 2;
}
mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
@ -123,11 +133,11 @@ mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interf
return neighbor;
}
static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, uint8_t attribute_index)
static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr)
{
mac_helper_devicetable_remove(interface->mac_api, attribute_index);
etx_neighbor_remove(interface->id, attribute_index);
ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, attribute_index);
mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index, entry_ptr->mac64);
etx_neighbor_remove(interface->id, entry_ptr->index);
ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, entry_ptr->index);
}
static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface)
@ -144,8 +154,9 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
}
if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
//Trig Address Registartion only when Bootstrap is ready
if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE || addr->source == ADDR_SOURCE_DHCP) {
ws_bootsrap_event_trig(WS_ADDRESS_ADDED, interface->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, (void *)addr);
if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE && addr->source != ADDR_SOURCE_DHCP) {
tr_debug("Address registration %s", trace_ipv6(addr->address));
rpl_control_register_address(interface, addr->address);
}
if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_LINK_LOCAL) {
// at least ula address available inside mesh.
@ -155,6 +166,12 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
} else if (reason == ADDR_CALLBACK_DELETED) {
// What to do?
// Go through address list and check if there is global address still available
if (addr->source == ADDR_SOURCE_DHCP) {
//Deprecate dhcpv address
uint8_t address[16];
memcpy(address, addr->address, 16);
dhcp_client_global_address_delete(interface->id, NULL, address);
}
//Discover prefix policy
addr_policy_remove_by_label(WS_NON_PREFFRED_LABEL);
@ -167,12 +184,10 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
}
}
} else if (reason == ADDR_CALLBACK_TIMER) {
tr_debug("Address Re registration %s", trace_ipv6(addr->address));
if (!interface->ws_info->address_registration_event_active) {
interface->ws_info->address_registration_event_active = true;
tr_info("Register ARO");
ws_bootsrap_event_trig(WS_ADDRESS_ADDED, interface->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL);
if (addr->source != ADDR_SOURCE_DHCP) {
tr_debug("Address Re registration %s", trace_ipv6(addr->address));
//Register
rpl_control_register_address(interface, addr->address);
}
}
}
@ -304,9 +319,7 @@ static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neigh
{
//Send NS
uint8_t ll_target[16];
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_target + 8, neighbor->mac64, 8);
ll_target[8] ^= 2;
ws_bootsrap_create_ll_address(ll_target, neighbor->mac64);
tr_info("NUD generate NS %u", neighbor->index);
buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL);
if (buffer) {
@ -321,6 +334,8 @@ void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
//Convert TICKS to real milliseconds
if (ticks > 0xffff / 100) {
ticks = 0xffff;
} else if (ticks == 0) {
ticks = 1;
} else {
ticks *= 100;
}
@ -649,10 +664,7 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 /*||
!ws_neighbour->candidate_parent*/) {
// if RSL value is not good enough candidate parent flag is removed and device not accepted as parent
//tr_debug("ws_etx_read not valid parent");
if (etx_entry && etx_entry->etx_samples) {
tr_debug("ws_etx_read not valid %u RSL IN(%u), %u RSL out(%u)", ws_neighbor_class_rsl_in_get(ws_neighbour), ws_neighbour->rsl_in, ws_neighbor_class_rsl_out_get(ws_neighbour), ws_neighbour->rsl_out);
}
tr_debug("ws_etx_read not valid params");
return 0xffff;
}
@ -680,6 +692,21 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
//tr_debug("ws_etx_read etx:%d", etx);
return etx;
}
bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq)
{
(void)cur;
(void)seq;
if (unicast) {
// Unicast NS is OK
return false;
}
// Fail the resolution
tr_warn("Link address lost for %s", trace_ipv6(entry->ip_address));
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, entry);
// True means we skip the message sending
return true;
}
static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
{
@ -698,8 +725,6 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
return -3;
}
//Enable Power bootup timer setup
cur->ws_info->power_up_setup = true;
// Save FHSS api
cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api);
@ -725,6 +750,9 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
/* Disable NUD Probes */
cur->ipv6_neighbour_cache.send_nud_probes = false;
cur->ipv6_neighbour_cache.probe_avoided_routers = true;
/*Replace NS handler to disable multicast address queries */
cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit;
dhcp_client_init(cur->id);
dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used.
dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC);
@ -833,17 +861,18 @@ static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interf
*
* A consistent transmission is defined as a PAN Advertisement received by a node with PAN ID and
* NETNAME-IE / Network Name matching that of the receiving node, and with a PAN-IE / Routing Cost
* the same or better than (less than or equal to) that of the receiving node.
* the same or worse than (bigger than or equal to) that of the receiving node.
*
* Inconsistent:
* PAN Advertisement solicit
*
* Received Routing Cost is smaller than stored one
*
* A PAN Advertisement received by a node with PAN ID and NETNAME-IE / Network name matching
* that of the receiving node, and PAN-IE / Routing Cost worse than (greater than) that of the receiving node.
* that of the receiving node, and PAN-IE / Routing Cost better than (smaller than) that of the receiving node.
*
*/
if (pan_information->routing_cost <= cur->ws_info->pan_information.routing_cost) {
if (pan_information->routing_cost >= cur->ws_info->pan_information.routing_cost) {
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement);
} else {
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery);
@ -897,7 +926,7 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
// Save route cost for all neighbours
llc_neighbour_req_t neighbor_info;
neighbor_info.neighbor = NULL;
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false, false)) {
neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost;
}
@ -911,13 +940,13 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
if (memcmp(cur->ws_info->parent_info.addr, ADDR_UNSPECIFIED, 8) != 0) {
// if we dont have higher than threshold signal only signal level decides parent
if (ws_neighbor_class_rssi_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm) < (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rssi_from_dbm_calculate(data->signal_dbm) > ws_neighbor_class_rssi_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm)) {
if (ws_neighbor_class_rsl_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rsl_from_dbm_calculate(data->signal_dbm) > ws_neighbor_class_rsl_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm)) {
// automatically select the best quality link from the below threshold
goto parent_selected;
}
// Drop if signal quality is not good enough
if (ws_neighbor_class_rssi_from_dbm_calculate(data->signal_dbm) < (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
if (ws_neighbor_class_rsl_from_dbm_calculate(data->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
tr_info("EAPOL target dropped Link quality too low");
return;
}
@ -936,14 +965,6 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
tr_info("EAPOL target dropped Lower link quality %u < %u current", data->signal_dbm, cur->ws_info->parent_info.signal_dbm);
return;
}
} else {
// First advertise heard
if (ws_neighbor_class_rssi_from_dbm_calculate(data->signal_dbm) < (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
// First neighbor is too low we need to wait one extra trickle
cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
}
}
parent_selected:
@ -974,8 +995,10 @@ parent_selected:
// Learn latest network information
if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && neighbor_info.neighbor) {
uint8_t ll_address[16];
ws_bootsrap_create_ll_address(ll_address, neighbor_info.neighbor->mac64);
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
if (rpl_control_is_dodag_parent(cur, ll_address, true)) {
cur->ws_info->pan_information.pan_size = pan_information.pan_size;
cur->ws_info->pan_information.routing_cost = pan_information.routing_cost;
cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method;
@ -1055,23 +1078,34 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
return;
}
llc_neighbour_req_t neighbor_info;
if (!ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true)) {
return;
bool neighbour_pointer_valid;
if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
//If we are border router or learned configuration we only update already learned neighbours.
neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false, true);
} else {
neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true, true);
if (!neighbour_pointer_valid) {
return;
}
}
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
//Update Neighbor Broadcast and Unicast Parameters
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
if (neighbour_pointer_valid) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
//Update Neighbor Broadcast and Unicast Parameters
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
}
if (cur->ws_info->configuration_learned) {
tr_info("PAN Config analyse own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version);
if (cur->ws_info->pan_information.pan_version == pan_version) {
// Same version heard so it is consistent
trickle_consistent_heard(&cur->ws_info->trickle_pan_config);
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_SOFT_SYNCH);
}
// no need to process more
@ -1079,7 +1113,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
} else {
// received version is different so we need to reset the trickle
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH);
}
if (common_serial_number_greater_16(cur->ws_info->pan_information.pan_version, pan_version)) {
@ -1100,7 +1134,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version);
// restart PAN version timer
cur->ws_info->pan_version_timeout_timer = PAN_VERSION_TIMEOUT;
cur->ws_info->pan_version_timeout_timer = ws_common_version_timeout_get(cur->ws_info->network_size_config);
cur->ws_info->pan_information.pan_version = pan_version;
ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr);
@ -1138,7 +1172,7 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
*/
llc_neighbour_req_t neighbor_info;
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false, false)) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
@ -1220,7 +1254,7 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c
default:
return;
}
ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1);
//UTT-IE and US-IE are mandatory for all Asynch Messages
ws_utt_ie_t ws_utt;
if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) {
@ -1273,9 +1307,21 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c
static void ws_bootstrap_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message)
{
ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1);
(void)interface;
(void)asynch_message;
}
uint32_t ws_time_from_last_unicast_traffic(uint32_t current_time_stamp, ws_neighbor_class_entry_t *ws_neighbor)
{
uint32_t time_from_last_unicast_shedule = current_time_stamp;
//Time from last RX unicast in us
time_from_last_unicast_shedule -= ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp;
time_from_last_unicast_shedule /= 1000000; //Convert to seconds
return time_from_last_unicast_shedule;
}
static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_entry *interface)
{
uint8_t ll_target[16];
@ -1286,14 +1332,22 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
}
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
uint32_t current_time_stamp = ns_sw_mac_read_current_timestamp(interface->mac_api);
mac_neighbor_table_entry_t *neighbor_entry_ptr = NULL;
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, cur->index);
if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) {
//This is our primary parent we cannot delete
continue;
}
if (cur->nud_active || ws_neighbor->accelerated_etx_probe || ws_neighbor->negative_aro_send) {
//If NUD process is active do not trig
continue;
}
if (neighbor_entry_ptr && neighbor_entry_ptr->lifetime < cur->lifetime) {
// We have already shorter link entry found this cannot replace it
continue;
@ -1309,20 +1363,35 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
memcpy(ll_target + 8, cur->mac64, 8);
ll_target[8] ^= 2;
if (rpl_control_is_dodag_parent(interface, ll_target)) {
if (rpl_control_is_dodag_parent(interface, ll_target, true)) {
// Possible parent is limited to 3 by default?
continue;
}
}
uint32_t link_min_timeout;
//Read current timestamp
uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor);
if (cur->trusted_device) {
neighbor_entry_ptr = cur;
link_min_timeout = WS_NEIGHBOR_TRUSTED_LINK_MIN_TIMEOUT;
} else {
if (cur->link_lifetime - cur->lifetime > WS_NEIGHBOR_NOT_TRUSTED_LINK_TIMEOUT) {
//Accept only Enough Old not trusted Device
link_min_timeout = WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT;
}
if (time_from_last_unicast_shedule > link_min_timeout || !ws_neighbor->unicast_data_rx) {
//Accept only Enough Old Device
if (!neighbor_entry_ptr) {
//Accept first compare
neighbor_entry_ptr = cur;
} else {
uint32_t compare_neigh_time = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor_entry_ptr->index));
if (compare_neigh_time < time_from_last_unicast_shedule) {
//Accept older RX timeout allways
neighbor_entry_ptr = cur;
}
}
}
}
@ -1333,7 +1402,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
}
static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new)
static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast)
{
neighbor_buffer->neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), mac_64, ADDR_802_15_4_LONG);
if (neighbor_buffer->neighbor) {
@ -1346,17 +1415,36 @@ static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_en
if (!request_new) {
return false;
}
uint8_t ll_target[16];
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_target + 8, mac_64, 8);
ll_target[8] ^= 2;
uint8_t ll_target[16];
ws_bootsrap_create_ll_address(ll_target, mac_64);
if (blacklist_reject(ll_target)) {
// Rejected by blacklist
return false;
}
if (multicast) {
//for multicast neighbour we must limit if we have already enough information
if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
//Border router never allocate neighbors by multicast
return false;
}
uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false);
//if we have enough candidates at list do not accept new multicast neighbours
if (parent_candidate_size >= 4) {
return false;
}
parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true);
//If we have already enough parent selected Candidates count is bigger tahn 4
if (parent_candidate_size >= 2) {
return false;
}
}
ws_bootstrap_neighbor_table_clean(interface);
neighbor_buffer->neighbor = ws_bootstrap_mac_neighbor_add(interface, mac_64);
@ -1394,7 +1482,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt
//NUD Process Clear Here
ws_nud_entry_remove(cur, entry_ptr);
ws_bootstrap_neighbor_delete(cur, entry_ptr->index);
ws_bootstrap_neighbor_delete(cur, entry_ptr);
}
static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
@ -1406,7 +1494,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, entry_ptr->index);
etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, entry_ptr->index);
if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry) {
if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send) {
return false;
}
@ -1426,17 +1514,37 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
//ETX Sample 0: random 1-8
//ETX Sample 1: random 2-16
//ETX Sample 2: random 4-32
uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples;
uint32_t time_block = 1 << etx_entry->etx_samples;
if (time_from_start >= probe_period) {
tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples);
if (etx_entry->etx_samples == 0 && ws_neighbor->accelerated_etx_probe) {
//Accept quick Probe for init ETX
activate_nud = true;
} else if (time_from_start > time_block) {
uint16_t switch_prob = randLIB_get_random_in_range(0, probe_period - 1);
//Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5
if (switch_prob < 2) {
tr_debug("Link Probe test with jitter %"PRIu32", sample %u", time_from_start, etx_entry->etx_samples);
} else {
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
if (etx_entry->etx_samples || !ws_neighbor->unicast_data_rx) {
//Border router just need 1 sample for ETX
return false;
}
} else {
uint8_t ll_address[16];
ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64);
if (!rpl_control_is_dodag_parent(cur, ll_address, false)) {
if (etx_entry->etx_samples || !ws_neighbor->unicast_data_rx) {
return 0;
}
}
}
uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples;
uint32_t time_block = 1 << etx_entry->etx_samples;
if (time_from_start >= probe_period) {
//tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples);
activate_nud = true;
} else if (time_from_start > time_block) {
uint16_t switch_prob = randLIB_get_random_in_range(0, probe_period - 1);
//Take Random from time WS_NEIGHBOR_NUD_TIMEOUT - WS_NEIGHBOR_NUD_TIMEOUT*1.5
if (switch_prob < 2) {
//tr_debug("Link Probe test with jitter %"PRIu32", sample %u", time_from_start, etx_entry->etx_samples);
activate_nud = true;
}
}
}
}
@ -1450,6 +1558,10 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
return false;
}
entry->neighbor_info = entry_ptr;
if (ws_neighbor->accelerated_etx_probe) {
ws_neighbor->accelerated_etx_probe = false;
entry->timer = 1;
}
if (etx_entry->etx_samples >= WS_NEIGBOR_ETX_SAMPLE_MAX) {
entry->nud_process = true;
@ -1554,7 +1666,7 @@ 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_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_pan_version_increment) < 0) {
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &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) < 0) {
ret_val = -4;
goto init_fail;
}
@ -1778,11 +1890,8 @@ static void ws_set_fhss_hop(protocol_interface_info_entry_t *cur)
static void ws_address_registration_update(protocol_interface_info_entry_t *interface)
{
if (!interface->ws_info->address_registration_event_active) {
interface->ws_info->address_registration_event_active = true;
tr_info("RPL parent update ... register ARO");
ws_bootsrap_event_trig(WS_ADDRESS_ADDED, interface->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, NULL);
}
rpl_control_register_address(interface, NULL);
tr_info("RPL parent update ... register ARO");
}
static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
@ -1835,7 +1944,13 @@ static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[
(void)prefix;
(void)interface;
//TODO add handler for negative status
tr_debug("DHCPv6 %s status %u", trace_ipv6(dhcp_addr), register_status);
tr_debug("DHCPv6 %s status %u with link %s", trace_ipv6(prefix), register_status, trace_ipv6(dhcp_addr));
if (register_status) {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
if (cur) {
rpl_control_register_address(cur, prefix);
}
}
}
@ -1907,6 +2022,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur)
rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, cur);
// If i am router I Do this
rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf);
rpl_control_request_parent_link_confirmation(true);
cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event
}
@ -1966,16 +2082,6 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
// New network scan started old addresses not assumed valid anymore
ws_bootstrap_ip_stack_addr_clear(cur);
// Reset advertisement solicit trickle to start discovering network
cur->ws_info->trickle_pas_running = true;
trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
if (cur->ws_info->power_up_setup) {
cur->ws_info->power_up_setup = false;
tr_debug("PAS init I %u and t %u", cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t);
} else {
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
}
if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) != INTERFACE_NWK_BOOTSRAP_ACTIVE) {
// we have sent bootstrap ready event and now
// restarted discovery so bootstrap down event is sent
@ -1983,8 +2089,24 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN);
}
// Discovery statemachine is checkked after two trickle interval
cur->bootsrap_state_machine_cnt = 2 * cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
// Start advertisement solicit trickle and calculate when we are checking the status
cur->ws_info->trickle_pas_running = true;
if (cur->ws_info->trickle_pan_advertisement_solicit.I != cur->ws_info->trickle_params_pan_discovery.Imin) {
// Trickle not reseted so starting a new interval
trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
}
// Discovery statemachine is checkked after we have sent the Solicit
uint16_t time_to_solicit = 0;
if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) {
time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now;
}
tr_debug("Disc params imin %u, imax %u, expirations %u, k %u PAS Trickle I %u t %u, now %u, c %u",
cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k,
cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c);
cur->bootsrap_state_machine_cnt = time_to_solicit + cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
}
// Start authentication
@ -2024,6 +2146,12 @@ static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *c
mac_helper_link_frame_counter_set(cur->id, counter);
}
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter)
{
// Read frame counter
mac_helper_link_frame_counter_read(cur->id, counter);
}
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success)
{
if (success) {
@ -2032,6 +2160,8 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_
} else {
tr_debug("authentication failed");
// What else to do to start over again...
// Trickle is reseted when entering to discovery from state 2
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
ws_bootstrap_event_discovery_start(cur);
}
}
@ -2244,17 +2374,6 @@ static void ws_bootstrap_pan_config(protocol_interface_info_entry_t *cur)
ws_llc_asynch_request(cur, &async_req);
}
static bool ws_bootstrap_address_registration_ongoing(protocol_interface_info_entry_t *cur)
{
ns_list_foreach(if_address_entry_t, addr, &cur->ip_addresses) {
if (addr->addr_reg_pend != 0) {
return true;
}
}
return false;
}
static void ws_bootstrap_event_handler(arm_event_s *event)
{
ws_bootsrap_event_type_e event_type;
@ -2301,7 +2420,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur);
ws_llc_set_gtkhash(cur, gtkhash);
cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME;
cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config);
// Set default parameters for FHSS when starting a discovery
ws_fhss_border_router_configure(cur);
@ -2378,12 +2497,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
ws_bootstrap_advertise_start(cur);
ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE);
break;
case WS_ADDRESS_ADDED:
cur->ws_info->address_registration_event_active = false;
if (!ws_bootstrap_address_registration_ongoing(cur)) {
rpl_control_register_address(cur, (if_address_entry_t *) event->data_ptr);
}
break;
default:
tr_err("Invalid event received");
break;
@ -2407,7 +2521,7 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur)
// Add EAPOL neighbour
llc_neighbour_req_t neighbor_info;
if (!ws_bootstrap_neighbor_info_request(cur, cur->ws_info->parent_info.addr, &neighbor_info, true)) {
if (!ws_bootstrap_neighbor_info_request(cur, cur->ws_info->parent_info.addr, &neighbor_info, true, false)) {
return;
}
@ -2515,9 +2629,6 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
break;
case ER_PANA_AUTH:
tr_info("authentication start");
// only advert sol stopped as we might be doing re authentication
cur->ws_info->trickle_pas_running = false;
//Add Test ecurity key and security level's
// Advertisements stopped during the EAPOL
cur->ws_info->trickle_pa_running = false;
cur->ws_info->trickle_pc_running = false;
@ -2557,6 +2668,8 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t
// Remove network keys from MAC
ws_pae_controller_nw_keys_remove(cur);
// Trickle is reseted when entering to discovery from state 3
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
ws_bootstrap_event_discovery_start(cur);
return;
}
@ -2601,9 +2714,7 @@ void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_ne
neighbor_info.ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index);
ws_bootstrap_primary_parent_set(interface, &neighbor_info, WS_PARENT_HARD_SYNCH);
uint8_t link_local_address[16];
memcpy(link_local_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(link_local_address + 8, neighbor->mac64, 8);
link_local_address[8] ^= 2;
ws_bootsrap_create_ll_address(link_local_address, neighbor->mac64);
dhcp_client_server_address_update(interface->id, NULL, link_local_address);
ws_secondary_parent_update(interface);
@ -2615,11 +2726,30 @@ void ws_secondary_parent_update(protocol_interface_info_entry_t *interface)
if (interface->ws_info) {
ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) {
if (!addr_is_ipv6_link_local(address->address)) {
address->addr_reg_done = 0;
ws_address_registration_update(interface);
}
}
}
}
void ws_bootstrap_etx_accelerate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh)
{
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neigh->index);
//Enable Faster ETX probing
ws_neighbor->accelerated_etx_probe = true;
//Move Neighbor to first to for accelerate Process
mac_neighbor_table_t *table_class = mac_neighbor_info(interface);
ns_list_remove(&table_class->neighbour_list, neigh);
ns_list_add_to_start(&table_class->neighbour_list, neigh);
//Try to Generate Active NUD Immediately
if (!ws_neighbor_entry_nud_notify(neigh, interface)) {
return;//Return if NUD active is full
}
table_class->active_nud_process++;
neigh->nud_active = true;
//Push NS to send
ws_nud_active_timer(interface, 0);
}
#endif //HAVE_WS

View File

@ -24,8 +24,7 @@ typedef enum {
WS_DISCOVERY_START, /**< discovery start*/
WS_CONFIGURATION_START, /**< configuration learn start*/
WS_OPERATION_START, /**< active operation start*/
WS_ROUTING_READY, /**< RPL routing connected to BR*/
WS_ADDRESS_ADDED /**< Address added to IF*/
WS_ROUTING_READY /**< RPL routing connected to BR*/
} ws_bootsrap_event_type_e;
#ifdef HAVE_WS
@ -77,6 +76,8 @@ bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur);
void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info);
void ws_bootstrap_etx_accelerate(struct protocol_interface_info_entry *cur, mac_neighbor_table_entry_t *neigh);
#else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
@ -86,6 +87,7 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur,
#define ws_bootstrap_aro_failure(cur, ll_address)
#define ws_primary_parent_update(interface, neighbor)
#define ws_secondary_parent_update(interface)
#define ws_bootstrap_etx_accelerate(cur, neigh) ((void) 0)
#endif //HAVE_WS

View File

@ -27,6 +27,7 @@
#include "6LoWPAN/ws/ws_common.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "ws_management_api.h"
@ -35,7 +36,9 @@
#ifdef HAVE_WS
#define TRACE_GROUP "wscm"
int8_t DEVICE_MIN_SENS = -93;
// estimated sensitivity -93 dbm converted to Wi-SUN RSL range
// This provides a range of -174 (0) to +80 (254) dBm
uint8_t DEVICE_MIN_SENS = 174 - 93;
#define TRICKLE_IMIN_60_SECS (60 * 10)
#define TRICKLE_IMIN_30_SECS (30 * 10)
@ -50,7 +53,7 @@ static const trickle_params_t trickle_params_pan_discovery_large = {
static const trickle_params_t trickle_params_pan_discovery_medium = {
.Imin = TRICKLE_IMIN_30_SECS, /* 30 second; ticks are 1s */
.Imax = TRICKLE_IMIN_30_SECS << 3, /* 240 seconds 4 min*/
.Imax = TRICKLE_IMIN_30_SECS << 5, /* 960 seconds 16 min*/
.k = 1, /* 1 */
.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
};
@ -274,8 +277,8 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
cur->ws_info->hopping_schdule.operating_class = 2;
ws_common_regulatory_domain_config(cur);
cur->ws_info->network_size_config = NETWORK_SIZE_AUTOMATIC;
ws_common_network_size_configure(cur, 10); // defaults to small network size
cur->ws_info->network_size_config = NETWORK_SIZE_MEDIUM;
ws_common_network_size_configure(cur, 200); // defaults to medium network size
// Set defaults for the device. user can modify these.
cur->ws_info->fhss_uc_fixed_channel = 0xffff;
@ -314,17 +317,17 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium;
// Something in between
// imin: 15 (32s)
// doublings:3 (262s)
// redundancy; 7
ws_bbr_rpl_config(15, 3, 7);
// doublings:5 (960s)
// redundancy; 10
ws_bbr_rpl_config(15, 5, 10);
} else {
// Configure the Wi-SUN discovery trickle parameters
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_large;
// Wi-SUN Large network parameters
// imin: 19 (524s, 9 min)
// doublings:1 (1048s, 17 min)
// redundancy; 1 Really heavy redundancy
ws_bbr_rpl_config(19, 1, 1);
// redundancy; 10 May need some tuning still
ws_bbr_rpl_config(19, 1, 10);
}
return;
}
@ -396,6 +399,58 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa
return true;
}
bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
{
mac_neighbor_table_entry_t *neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(interface), eui64, ADDR_802_15_4_LONG);
if (!neighbour) {
return false;
}
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index);
ws_neighbor->negative_aro_send = true;
neighbour->lifetime = WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT; //Remove anyway if Packet is freed before MAC push
return true;
}
void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh)
{
etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, neigh->index);
if (neigh->nud_active || !neigh->trusted_device || !etx_entry || etx_entry->etx_samples) {
return; //Do not trig Second NS if Active NUD already, not trusted or ETX samples already done
}
ws_bootstrap_etx_accelerate(interface, neigh);
}
uint32_t ws_common_version_lifetime_get(uint8_t config)
{
uint32_t lifetime;
if (config == NETWORK_SIZE_SMALL) {
lifetime = PAN_VERSION_SMALL_NETWORK_LIFETIME;
} else if (config == NETWORK_SIZE_MEDIUM) {
lifetime = PAN_VERSION_MEDIUM_NETWORK_LIFETIME;
} else {
lifetime = PAN_VERSION_LARGE_NETWORK_LIFETIME;
}
return lifetime;
}
uint32_t ws_common_version_timeout_get(uint8_t config)
{
uint32_t lifetime;
if (config == NETWORK_SIZE_SMALL) {
lifetime = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
} else if (config == NETWORK_SIZE_MEDIUM) {
lifetime = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
} else {
lifetime = PAN_VERSION_LARGE_NETWORK_TIMEOUT;
}
return lifetime;
}
#endif // HAVE_WS

View File

@ -73,13 +73,11 @@ typedef struct ws_info_s {
uint32_t pan_version_timer; /**< border router version udate timeout */
uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */
uint8_t gtkhash[32];
bool address_registration_event_active : 1;
bool configuration_learned: 1;
bool trickle_pas_running: 1;
bool trickle_pa_running: 1;
bool trickle_pcs_running: 1;
bool trickle_pc_running: 1;
bool power_up_setup: 1;
// default fhss parameters for this device
uint8_t fhss_uc_dwell_interval;
uint8_t fhss_bc_dwell_interval;
@ -94,6 +92,7 @@ typedef struct ws_info_s {
ws_nud_table_list_t free_nud_entries;
struct ws_pan_information_s pan_information;
ws_hopping_schedule_t hopping_schdule;
struct ws_statistics *stored_stats_ptr;
struct ws_neighbor_class_s neighbor_storage;
struct fhss_timer *fhss_timer_ptr; // Platform adaptation for FHSS timers.
struct fhss_api *fhss_api;
@ -123,6 +122,15 @@ void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64);
void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neigh);
bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64);
uint32_t ws_common_version_lifetime_get(uint8_t config);
uint32_t ws_common_version_timeout_get(uint8_t config);
#define ws_info(cur) ((cur)->ws_info)
#else
#define ws_info(cur) ((ws_info_t *) NULL)
@ -132,6 +140,8 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, co
#define ws_common_neighbor_remove(cur, ll_address)
#define ws_common_fast_timer(cur, ticks) ((void) 0)
#define ws_common_allow_child_registration(cur, eui64) (false)
#define ws_common_etx_validate(interface, neigh) ((void) 0)
#define ws_common_negative_aro_mark(interface, eui64)(false)
#endif //HAVE_WS

View File

@ -186,7 +186,8 @@ typedef struct ws_bs_ie {
#define WS_FAN_VERSION_1_0 1
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
#define WS_NEIGHBOR_NOT_TRUSTED_LINK_TIMEOUT 60
#define WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT 60
#define WS_NEIGHBOR_TRUSTED_LINK_MIN_TIMEOUT 15
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
#define WS_NEIGBOR_ETX_SAMPLE_MAX 3

View File

@ -37,7 +37,9 @@
* Minimum interval at which a Border Router shall increment its PAN Version value.
*/
#define PAN_VERSION_LIFETIME 240
#define PAN_VERSION_SMALL_NETWORK_LIFETIME 4*60
#define PAN_VERSION_MEDIUM_NETWORK_LIFETIME 15*60
#define PAN_VERSION_LARGE_NETWORK_LIFETIME 30*60 //30min
#define RPL_VERSION_LIFETIME 5*3600
@ -50,7 +52,11 @@
*
*/
#define PAN_VERSION_TIMEOUT 1920
#define PAN_VERSION_SMALL_NETWORK_TIMEOUT 32*60
#define PAN_VERSION_MEDIUM_NETWORK_TIMEOUT 64*60
#define PAN_VERSION_LARGE_NETWORK_TIMEOUT 90*60
/* Routing Cost Weighting factor
*/
@ -68,7 +74,7 @@
*
* Default value for us is -93
*/
extern int8_t DEVICE_MIN_SENS;
extern uint8_t DEVICE_MIN_SENS;
/* Candidate parent Threshold
*/
@ -96,7 +102,7 @@ extern int8_t DEVICE_MIN_SENS;
*
*/
#define WS_DHCP_SOLICIT_TIMEOUT 60
#define WS_DHCP_SOLICIT_MAX_RT 3600
#define WS_DHCP_SOLICIT_MAX_RT 900
#define WS_DHCP_SOLICIT_MAX_RC 0
@ -120,5 +126,11 @@ extern int8_t DEVICE_MIN_SENS;
#define WS_BLACKLIST_PURGE_NBR 3
#define WS_BLACKLIST_PURGE_TIMER_TIMEOUT 60
/*
* MAC frame counter NVM storing configuration
*/
#define FRAME_COUNTER_STORE_INTERVAL 60 // Time interval (on seconds) between frame counter store operations
#define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up
#define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored
#endif /* WS_CONFIG_H_ */

View File

@ -189,4 +189,17 @@ int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4])
return -1;
}
int ws_statistics_start(int8_t interface_id, ws_statistics_t *stats_ptr)
{
(void) interface_id;
(void) stats_ptr;
return -1;
}
int ws_statistics_stop(int8_t interface_id)
{
(void) interface_id;
return -1;
}
#endif // no HAVE_WS

View File

@ -111,10 +111,10 @@ uint8_t *ws_wh_fc_write(uint8_t *ptr, uint8_t flow_ctrl)
return ptr;
}
uint8_t *ws_wh_rsl_write(uint8_t *ptr, int8_t rssi)
uint8_t *ws_wh_rsl_write(uint8_t *ptr, uint8_t rsl)
{
ptr = ws_wh_header_base_write(ptr, 1, WH_IE_RSL_TYPE);
*ptr++ = rssi;
*ptr++ = rsl;
return ptr;
}

View File

@ -36,7 +36,7 @@ typedef struct ws_wp_network_name {
uint8_t *ws_wh_utt_write(uint8_t *ptr, uint8_t message_type);
uint8_t *ws_wh_bt_write(uint8_t *ptr);
uint8_t *ws_wh_fc_write(uint8_t *ptr, uint8_t flow_ctrl);
uint8_t *ws_wh_rsl_write(uint8_t *ptr, int8_t rssi);
uint8_t *ws_wh_rsl_write(uint8_t *ptr, uint8_t rsl);
uint8_t *ws_wh_vh_write(uint8_t *ptr, uint8_t *vendor_header, uint8_t vendor_header_length);
uint8_t *ws_wh_ea_write(uint8_t *ptr, uint8_t *eui64);

View File

@ -99,11 +99,12 @@ typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface,
* @param mac_64 Neighbor 64-bit address
* @param neighbor_buffer Buffer where neighbor infor is buffered
* @param request_new true if is possible to allocate new entry
* @param multicast true if packet is multicast
*
* @return true when neighbor info is available
* @return false when no neighbor info
*/
typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new);
typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast);
/**
* @brief ws_llc_create ws LLC module create

View File

@ -395,7 +395,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
success = true;
}
if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false)) {
if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false, false)) {
etx_transm_attempts_update(interface->id, 1 + data->tx_retries, success, neighbor_info.neighbor->index);
//TODO discover RSL from Enchanced ACK Header IE elements
ws_utt_ie_t ws_utt;
@ -463,8 +463,7 @@ static void ws_llc_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_
//Write Data to block
uint8_t *ptr = base->ws_enhanced_ack_elements;
ptr = ws_wh_utt_write(ptr, WS_FT_ACK);
uint8_t rsl = ws_neighbor_class_rssi_from_dbm_calculate(rssi);
ws_wh_rsl_write(ptr, rsl);
ws_wh_rsl_write(ptr, ws_neighbor_class_rsl_from_dbm_calculate(rssi));
}
/** WS LLC MAC data extension indication */
@ -494,6 +493,7 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
return;
}
mpx_user_t *user_cb;
mac_payload_IE_t mpx_ie;
mpx_ie.id = MAC_PAYLOAD_MPX_IE_GROUP_ID;
if (mac_ie_payload_discover(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &mpx_ie) < 1) {
@ -522,12 +522,24 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
}
llc_neighbour_req_t neighbor_info;
if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, us_ie_inline)) {
tr_debug("Drop message no neighbor");
return;
bool multicast;
if (data->DstAddrMode == ADDR_802_15_4_LONG) {
multicast = false;
} else {
multicast = true;
}
if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, us_ie_inline, multicast)) {
if (!multicast || ws_utt.message_type == WS_FT_EAPOL) {
tr_debug("Drop message no neighbor");
return;
} else {
goto mpx_data_ind;
}
}
multicast = false;
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
if (us_ie_inline) {
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie);
@ -557,9 +569,9 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
}
}
//Refresh Neighbor if unicast
//Refresh Neighbor ETX if unicast
if (ws_utt.message_type == WS_FT_DATA && data->DstAddrMode == ADDR_802_15_4_LONG) {
neighbor_info.neighbor->lifetime = neighbor_info.neighbor->link_lifetime;
neighbor_info.ws_neighbor->unicast_data_rx = true;
etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
}
if (ws_utt.message_type == WS_FT_DATA) {
@ -572,10 +584,15 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
}
}
mpx_data_ind:
// Discover MPX
mpx_user_t *user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, mpx_frame.multiplex_id);
user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, mpx_frame.multiplex_id);
if (user_cb && user_cb->data_ind) {
mcps_data_ind_t data_ind = *data;
if (multicast) {
data_ind.Key.SecurityLevel = 0; //Mark unknow device
}
data_ind.msdu_ptr = mpx_frame.frame_ptr;
data_ind.msduLength = mpx_frame.frame_length;
user_cb->data_ind(&base->mpx_data_base.mpx_api, &data_ind);
@ -618,7 +635,7 @@ static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id)
}
//Dynamic length
header_size += 2 + WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, true);
header_size += 2 + WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, true) + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, false);
} else if (MPX_KEY_MANAGEMENT_ENC_USER_ID) {
header_size += 7 + 5 + 2;
@ -687,6 +704,11 @@ static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data
if (base->ie_params.vendor_payload_length) {
nested_wp_id.vp_ie = true;
}
if (!data->TxAckReq) {
nested_wp_id.bs_ie = true;
}
} else if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) {
ie_header_mask.bt_ie = ws_eapol_relay_state_active(base->interface_ptr);
ie_header_mask.ea_ie = ws_eapol_handshake_first_msg(data->msdu, data->msduLength, base->interface_ptr);

View File

@ -118,6 +118,8 @@ int ws_management_network_size_set(
if (network_size == NETWORK_SIZE_LARGE) {
ws_common_network_size_configure(cur, 5000);
} else if (network_size == NETWORK_SIZE_MEDIUM) {
ws_common_network_size_configure(cur, 200);
} else {
ws_common_network_size_configure(cur, 10);
}

View File

@ -134,13 +134,22 @@ void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t
ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id = ws_bs_ie->broadcast_schedule_identifier;
}
uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard)
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard)
{
if (DEVICE_MIN_SENS > dbm_heard) {
if (DEVICE_MIN_SENS > rsl_heard) {
// We are hearing packet with lower than min_sens dynamically learn the sensitivity
DEVICE_MIN_SENS = dbm_heard;
DEVICE_MIN_SENS = rsl_heard;
}
return dbm_heard - DEVICE_MIN_SENS;
}
uint8_t ws_neighbor_class_rsl_from_dbm_calculate(int8_t dbm_heard)
{
/* RSL MUST be calculated as the received signal level relative to standard
* thermal noise (290oK) at 1 Hz bandwidth or 174 dBm.
* This provides a range of -174 (0) to +80 (254) dBm.
*/
return dbm_heard + 174;
}
static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_neighbor)
@ -151,24 +160,26 @@ static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_n
return;
}
if (ws_neighbor_class_rsl_in_get(ws_neighbor) < (CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rsl_out_get(ws_neighbor) < (CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS)) {
if (ws_neighbor_class_rsl_in_get(ws_neighbor) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rsl_out_get(ws_neighbor) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS)) {
ws_neighbor->candidate_parent = false;
}
if (ws_neighbor_class_rsl_in_get(ws_neighbor) > (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rsl_out_get(ws_neighbor) > (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
if (ws_neighbor_class_rsl_in_get(ws_neighbor) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
ws_neighbor_class_rsl_out_get(ws_neighbor) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
ws_neighbor->candidate_parent = true;
}
}
void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard)
{
uint8_t rssi = ws_neighbor_class_rssi_from_dbm_calculate(dbm_heard);
uint8_t rsl = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard);
// Calculate minimum sensitivity from heard packets.
ws_neighbor_class_rf_sensitivity_calculate(rsl);
if (ws_neighbor->rsl_in == RSL_UNITITIALIZED) {
ws_neighbor->rsl_in = rssi << WS_RSL_SCALING;
ws_neighbor->rsl_in = rsl << WS_RSL_SCALING;
}
ws_neighbor->rsl_in = ws_neighbor->rsl_in + rssi - (ws_neighbor->rsl_in >> WS_RSL_SCALING);
ws_neighbor->rsl_in = ws_neighbor->rsl_in + rsl - (ws_neighbor->rsl_in >> WS_RSL_SCALING);
ws_neighbor_class_parent_set_analyze(ws_neighbor);
return;
}

View File

@ -32,6 +32,9 @@ typedef struct ws_neighbor_class_entry {
bool broadcast_timing_info_stored: 1;
bool broadcast_shedule_info_stored: 1;
bool synch_done : 1;
bool accelerated_etx_probe : 1;
bool negative_aro_send : 1;
bool unicast_data_rx : 1;
} ws_neighbor_class_entry_t;
/**
@ -134,15 +137,26 @@ void ws_neighbor_class_neighbor_broadcast_time_info_update(ws_neighbor_class_ent
void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_bs_ie_t *ws_bs_ie);
/**
* ws_neighbor_class_rssi_from_dbm_calculate
* ws_neighbor_class_rf_sensitivity_calculate
*
* Calculates rssi value from dbm heard taking into account min sensitivity of radio
* dynamically adjusts min sensitivity if value is not properly set
* Calculates minimum heard RSL value from all packets.
* This will dynamically adjusts min sensitivity if value is not properly set
*
* \param rsl_heard; rsl_heard heard from Radio
*
*/
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard);
/**
* ws_neighbor_class_rsl_from_dbm_calculate
*
* Calculates rsl value from dbm heard.
* This provides a range of -174 (0) to +80 (254) dBm.
*
* \param dbm_heard; dbm heard from the neighbour
*
*/
uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard);
uint8_t ws_neighbor_class_rsl_from_dbm_calculate(int8_t dbm_heard);
/** Helper macros to read RSL values from neighbour class.
*

View File

@ -332,7 +332,7 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p
sec_prot_keys_pmk_delete(&supp->sec_keys);
sec_prot_keys_ptk_delete(&supp->sec_keys);
supp->access_revoked = true;
tr_info("Access revoked; keys removed, eui-64: %s", trace_array(kmp_address_eui_64_get(supp->addr), 8));
tr_info("Access revoked; keys removed, eui-64: %s", trace_array(supp->addr.eui_64, 8));
return 0;
}
@ -340,7 +340,7 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p
supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, eui_64);
if (supp) {
// Deletes supplicant
tr_info("Access revoked; deleted, eui-64: %s", trace_array(kmp_address_eui_64_get(supp->addr), 8));
tr_info("Access revoked; deleted, eui-64: %s", trace_array(supp->addr.eui_64, 8));
ws_pae_lib_supp_list_remove(&pae_auth->inactive_supp_list, supp);
return 0;
}
@ -720,8 +720,8 @@ static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *
// Get supplicant address
supp_entry_t *entry = kmp_api_data_get(kmp);
if (entry && entry->addr) {
kmp_address_copy(remote_addr, entry->addr);
if (entry) {
kmp_address_copy(remote_addr, &entry->addr);
}
}
@ -767,7 +767,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
sec_prot_keys_ptk_eui_64_write(&supp_entry->sec_keys, kmp_address_eui_64_get(addr));
} else {
// Updates relay address
kmp_address_copy(supp_entry->addr, addr);
kmp_address_copy(&supp_entry->addr, addr);
}
// Increases waiting time for supplicant authentication
@ -788,7 +788,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
kmp_api_data_set(kmp, supp_entry);
// Sets address to KMP
kmp_api_addr_set(kmp, supp_entry->addr);
kmp_api_addr_set(kmp, &supp_entry->addr);
// Sets security keys to KMP
kmp_api_sec_keys_set(kmp, &supp_entry->sec_keys);
@ -862,6 +862,11 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
if (next_type == KMP_TYPE_NONE) {
// All done
return;
} else {
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type) != NULL) {
tr_info("KMP already ongoing; ignored, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
return;
}
}
// Increases waiting time for supplicant authentication
@ -877,7 +882,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA);
if (ongoing_eap_tls_cnt >= MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS) {
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(kmp_address_eui_64_get(supp_entry->addr), 8));
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;
}
}
@ -902,7 +907,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
}
}
kmp_api_create_request(new_kmp, next_type, supp_entry->addr, &supp_entry->sec_keys);
kmp_api_create_request(new_kmp, next_type, &supp_entry->addr, &supp_entry->sec_keys);
}
static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry)
@ -915,11 +920,11 @@ static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry)
sec_keys->ptk_mismatch = true;
// start EAP-TLS towards supplicant
next_type = IEEE_802_1X_MKA;
tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 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(kmp_address_eui_64_get(supp_entry->addr), 8));
tr_info("PAE start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
}
int8_t gtk_index = -1;
@ -937,14 +942,14 @@ static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry)
if (next_type == KMP_TYPE_NONE && gtk_index >= 0) {
// Update just GTK
next_type = IEEE_802_11_GKH;
tr_info("PAE start GKH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 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(kmp_address_eui_64_get(supp_entry->addr), 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(kmp_address_eui_64_get(supp_entry->addr), 8));
tr_info("PAE authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
}
return next_type;
@ -1004,7 +1009,7 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *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(kmp_address_eui_64_get(retry_supp->addr), 8));
tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8));
ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp);
}

View File

@ -31,6 +31,8 @@
#include "6LoWPAN/ws/ws_pae_timers.h"
#include "6LoWPAN/ws/ws_pae_supp.h"
#include "6LoWPAN/ws/ws_pae_auth.h"
#include "6LoWPAN/ws/ws_pae_nvm_store.h"
#include "6LoWPAN/ws/ws_pae_nvm_data.h"
#include "mbedtls/sha256.h"
#ifdef HAVE_WS
@ -51,6 +53,13 @@ typedef struct {
bool fresh : 1; /**< Key is fresh i.e. not used on sending */
} nw_key_t;
typedef struct {
uint8_t hash[8]; /**< GTK hash for the frame counter */
uint32_t frame_counter; /**< Frame counter */
uint8_t index; /**< Index */
bool set : 1; /**< Value has been set */
} stored_frame_counter_t;
typedef struct {
ns_list_link_t link; /**< Link */
uint8_t target_eui_64[8]; /**< EAPOL target */
@ -63,6 +72,8 @@ typedef struct {
sec_prot_certs_t certs; /**< Certificates */
nw_key_t nw_key[4]; /**< Currently active network keys (on MAC) */
char *network_name; /**< Network name for GAK generation */
uint16_t frame_cnt_store_timer; /**< Timer for storing frame counter value */
stored_frame_counter_t stored_frame_counter; /**< Stored frame counter */
timer_settings_t timer_settings; /**< Timer settings */
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
@ -70,6 +81,7 @@ typedef struct {
ws_pae_controller_nw_key_clear *nw_key_clear; /**< Key clear callback */
ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set; /**< Send key index set callback */
ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set; /**< Frame counter set callback */
ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read; /**< Frame counter read callback */
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
ws_pae_delete *pae_delete; /**< PAE delete callback */
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
@ -79,12 +91,17 @@ typedef struct {
ws_pae_gtks_updated *pae_gtks_updated; /**< PAE GTKs updated */
ws_pae_gtk_hash_update *pae_gtk_hash_update; /**< PAE GTK HASH update */
ws_pae_nw_key_index_update *pae_nw_key_index_update; /**< PAE NW key index update */
nvm_tlv_entry_t *pae_nvm_buffer; /**< Buffer For PAE NVM write operation*/
bool gtks_set : 1; /**< GTKs are set */
bool gtkhash_set : 1; /**< GTK hashes are set */
bool key_index_set : 1; /**< NW key index is set */
} pae_controller_t;
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);
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry);
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry);
static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter);
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
@ -93,6 +110,12 @@ static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t
static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name);
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
static void ws_pae_controller_data_init(pae_controller_t *controller);
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller);
static void ws_pae_controller_frame_counter_reset(stored_frame_counter_t *counter);
static uint32_t ws_pae_controller_frame_counter_get(stored_frame_counter_t *counter, uint8_t index, uint8_t *key_hash);
static void ws_pae_controller_frame_counter_write(pae_controller_t *controller, uint8_t index, uint8_t *key_hash, uint32_t curr_counter);
static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
@ -188,7 +211,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_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_pan_ver_increment *pan_ver_increment)
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, 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)
{
if (!interface_ptr) {
return -1;
@ -204,6 +227,7 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
controller->nw_key_clear = nw_key_clear;
controller->nw_send_key_index_set = nw_send_key_index_set;
controller->nw_frame_counter_set = nw_frame_counter_set;
controller->nw_frame_counter_read = nw_frame_counter_read;
controller->pan_ver_increment = pan_ver_increment;
return 0;
@ -422,7 +446,12 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info
if (controller->nw_send_key_index_set) {
tr_info("NW send key index set: %i", index + 1);
controller->nw_send_key_index_set(interface_ptr, index);
controller->nw_frame_counter_set(interface_ptr, 0);
controller->gtk_index = index;
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
controller->nw_frame_counter_set(interface_ptr, frame_counter);
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
}
// Do not update PAN version for initial key index set
@ -444,10 +473,14 @@ static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t
if (controller->nw_send_key_index_set) {
controller->nw_send_key_index_set(controller->interface_ptr, index);
tr_info("NW send key index set: %i", index + 1);
// If index has changed and the key for the index is fresh reset frame counter
// If index has changed and the key for the index is fresh get frame counter
if (controller->gtk_index != index && controller->nw_key[index].fresh) {
controller->nw_frame_counter_set(cur, 0);
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
controller->nw_frame_counter_set(cur, frame_counter);
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
}
controller->gtk_index = index;
@ -466,7 +499,11 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
}
pae_controller_t *controller = ns_dyn_mem_alloc(sizeof(pae_controller_t));
if (!controller) {
void *pae_nvm_buffer = ws_pae_buffer_allocate();
if (!controller || !pae_nvm_buffer) {
ns_dyn_mem_free(controller);
ns_dyn_mem_free(pae_nvm_buffer);
return -1;
}
@ -477,6 +514,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
controller->nw_send_key_index_set = NULL;
controller->nw_frame_counter_set = NULL;
controller->pan_ver_increment = NULL;
controller->pae_nvm_buffer = pae_nvm_buffer;
ws_pae_controller_data_init(controller);
@ -510,12 +548,62 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
controller->key_index_set = false;
controller->gtk_index = -1;
controller->network_name = NULL;
controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
ws_pae_controller_frame_counter_reset(&controller->stored_frame_counter);
sec_prot_keys_gtks_init(&controller->gtks);
sec_prot_keys_gtks_init(&controller->next_gtks);
sec_prot_certs_init(&controller->certs);
ws_pae_timers_settings_init(&controller->timer_settings);
}
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller)
{
stored_frame_counter_t *counter = &controller->stored_frame_counter;
// If not already, read frame counter and check if index and hash matches
if (!counter->set && ws_pae_controller_nvm_frame_counter_read(&counter->index, counter->hash, &counter->frame_counter) >= 0) {
counter->frame_counter += FRAME_COUNTER_INCREMENT;
counter->set = true;
tr_debug("Read frame counter: %"PRIu32", index %i, hash %s, system time: %"PRIu32"", counter->frame_counter, counter->index, trace_array(counter->hash, 8), protocol_core_monotonic_time / 10);
// Write incremented frame counter
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, counter->index, counter->hash, counter->frame_counter);
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
}
}
static void ws_pae_controller_frame_counter_reset(stored_frame_counter_t *counter)
{
memset(counter->hash, 0, GTK_HASH_LEN);
counter->frame_counter = 0;
counter->index = -1;
counter->set = false;
}
static uint32_t ws_pae_controller_frame_counter_get(stored_frame_counter_t *counter, uint8_t index, uint8_t *key_hash)
{
uint32_t frame_counter = 0;
// If both index and hash matches uses the stored frame counter
if (counter->set && counter->index == index && memcmp(counter->hash, key_hash, GTK_HASH_LEN) == 0) {
frame_counter = counter->frame_counter;
}
return frame_counter;
}
static void ws_pae_controller_frame_counter_write(pae_controller_t *controller, uint8_t index, uint8_t *key_hash, uint32_t curr_frame_counter)
{
stored_frame_counter_t *counter = &controller->stored_frame_counter;
// If index or hash changes, or frame counter has been incremented by the threshold updates frame counter
if (!counter->set || counter->index != index || memcmp(key_hash, counter->hash, 8) != 0 || curr_frame_counter > counter->frame_counter + FRAME_COUNTER_STORE_THRESHOLD) {
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, index, key_hash, curr_frame_counter);
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
counter->index = index;
counter->frame_counter = curr_frame_counter;
memcpy(counter->hash, key_hash, GTK_HASH_LEN);
counter->set = true;
tr_debug("Stored frame counter: %"PRIu32", index %i, hash %s, system time: %"PRIu32"", curr_frame_counter, index, trace_array(key_hash, 8), protocol_core_monotonic_time / 10);
}
}
int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr)
{
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -537,6 +625,8 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set);
ws_pae_controller_frame_counter_read(controller);
return 0;
}
@ -557,8 +647,11 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
controller->pae_gtks_updated = ws_pae_auth_gtks_updated;
controller->pae_nw_key_index_update = ws_pae_auth_nw_key_index_update;
ws_pae_controller_frame_counter_read(controller);
return 0;
}
int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
{
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -566,6 +659,9 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
return -1;
}
// Stores frame counter
ws_pae_controller_frame_counter_store(controller);
// If PAE has been initialized, deletes it
if (controller->pae_delete) {
controller->pae_delete(interface_ptr);
@ -594,6 +690,7 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
}
ns_list_remove(&pae_controller_list, controller);
ns_dyn_mem_free(controller->pae_nvm_buffer);
ns_dyn_mem_free(controller);
return 0;
@ -959,9 +1056,58 @@ void ws_pae_controller_slow_timer(uint16_t seconds)
if (entry->pae_slow_timer) {
entry->pae_slow_timer(seconds);
}
ws_pae_controller_frame_counter_timer(seconds, entry);
}
}
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry)
{
if (entry->frame_cnt_store_timer > seconds) {
entry->frame_cnt_store_timer -= seconds;
} else {
entry->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
ws_pae_controller_frame_counter_store(entry);
}
}
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry)
{
// Gets index of active GTK
int8_t active_index = entry->gtk_index;
if (active_index >= 0) {
// Gets hash of the key
uint8_t *hash = entry->nw_key[active_index].hash;
uint32_t curr_frame_counter;
entry->nw_frame_counter_read(entry->interface_ptr, &curr_frame_counter);
ws_pae_controller_frame_counter_write(entry, active_index, hash, curr_frame_counter);
}
}
static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter)
{
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, &tlv_list) < 0) {
return -1;
}
int8_t result = -1;
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
if (ws_pae_nvm_store_frame_counter_tlv_read(entry, index, hash, frame_counter) >= 0) {
result = 0;
}
ns_list_remove(&tlv_list, entry);
ns_dyn_mem_free(entry);
}
return result;
}
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr)
{
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
@ -992,5 +1138,24 @@ static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id)
return controller;
}
nvm_tlv_entry_t *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr)
{
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
if (!controller) {
return NULL;
}
return controller->pae_nvm_buffer;
}
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry)
{
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, &tlv_list);
}
#endif /* HAVE_WS */

View File

@ -20,6 +20,7 @@
#ifdef HAVE_WS
struct nvm_tlv_entry;
/**
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
*
@ -384,6 +385,15 @@ typedef void ws_pae_controller_nw_send_key_index_set(protocol_interface_info_ent
*/
typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entry_t *interface_ptr, uint32_t counter);
/**
* ws_pae_controller_nw_frame_counter_read network frame counter read callback
*
* \param interface_ptr interface
* \param counter frame counter
*
*/
typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter);
/**
* ws_pae_controller_auth_completed authentication completed callback
*
@ -410,13 +420,14 @@ typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t
* \param nw_key_clear network key clear callback
* \param nw_send_key_index_set network send key index set callback
* \param nw_frame_counter_set network frame counter set callback
* \param nw_frame_counter_read network frame counter read callback
* \param pan_ver_increment PAN version increment 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_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_pan_ver_increment *pan_ver_increment);
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, 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_fast_timer PAE controller fast timer call
@ -435,6 +446,8 @@ void ws_pae_controller_fast_timer(uint16_t ticks);
*/
void ws_pae_controller_slow_timer(uint16_t seconds);
struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr);
#else
#define ws_pae_controller_set_target(interface_ptr, target_pan_id, target_dest_eui_64)
@ -455,6 +468,7 @@ void ws_pae_controller_slow_timer(uint16_t seconds);
#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_nvm_tlv_get(interface_ptr) NULL
#endif

View File

@ -156,9 +156,9 @@ supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t
}
ws_pae_lib_supp_init(entry);
entry->addr = kmp_address_create(KMP_ADDR_EUI_64_AND_IP, 0);
kmp_address_copy(entry->addr, addr);
memset(&entry->addr, 0, sizeof(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);
@ -178,7 +178,7 @@ int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *supp)
supp_entry_t *ws_pae_lib_supp_list_entry_eui_64_get(const supp_list_t *supp_list, const uint8_t *eui_64)
{
ns_list_foreach(supp_entry_t, cur, supp_list) {
if (memcmp(kmp_address_eui_64_get(cur->addr), eui_64, 8) == 0) {
if (memcmp(cur->addr.eui_64, eui_64, 8) == 0) {
return cur;
}
}
@ -213,10 +213,10 @@ void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settin
{
ns_list_foreach(supp_entry_t, entry, supp_list) {
if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, timer_settings->pmk_lifetime, seconds)) {
tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(kmp_address_eui_64_get(entry->addr), 8), protocol_core_monotonic_time / 10);
tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
}
if (sec_prot_keys_ptk_lifetime_decrement(&entry->sec_keys, timer_settings->ptk_lifetime, seconds)) {
tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(kmp_address_eui_64_get(entry->addr), 8), protocol_core_monotonic_time / 10);
tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
}
}
@ -225,7 +225,7 @@ void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settin
void ws_pae_lib_supp_init(supp_entry_t *entry)
{
ws_pae_lib_kmp_list_init(&entry->kmp_list);
entry->addr = 0;
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;
@ -236,7 +236,6 @@ void ws_pae_lib_supp_init(supp_entry_t *entry)
void ws_pae_lib_supp_delete(supp_entry_t *entry)
{
ws_pae_lib_kmp_list_free(&entry->kmp_list);
kmp_address_delete(entry->addr);
}
bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
@ -260,7 +259,7 @@ bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_li
entry->retry_ticks -= ticks;
} else {
if (entry->retry_ticks > 0) {
tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
}
entry->retry_ticks = 0;
}
@ -279,7 +278,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
return;
}
tr_debug("PAE: to active, eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
tr_debug("PAE: to active, eui-64: %s", trace_array(entry->addr.eui_64, 8));
ns_list_remove(inactive_supp_list, entry);
ns_list_add_to_start(active_supp_list, entry);
@ -288,9 +287,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
entry->ticks = 0;
// Adds relay address data
kmp_addr_t *addr = kmp_address_create(KMP_ADDR_EUI_64_AND_IP, kmp_address_eui_64_get(entry->addr));
kmp_address_delete(entry->addr);
entry->addr = addr;
entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
}
void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry)
@ -299,10 +296,10 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
return;
}
tr_debug("PAE: to inactive, eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
tr_debug("PAE: to inactive, eui-64: %s", trace_array(entry->addr.eui_64, 8));
if (entry->access_revoked) {
tr_info("Access revoked; deleted, eui-64: %s", trace_array(kmp_address_eui_64_get(entry->addr), 8));
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);
return;
}
@ -314,9 +311,9 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
entry->ticks = 0;
// Removes relay address data
kmp_addr_t *addr = kmp_address_create(KMP_ADDR_EUI_64, kmp_address_eui_64_get(entry->addr));
kmp_address_delete(entry->addr);
entry->addr = addr;
entry->addr.type = KMP_ADDR_EUI_64;
entry->addr.port = 0;
memset(entry->addr.relay_address, 0, 16);
}
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)

View File

@ -33,7 +33,7 @@ typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t;
typedef struct {
kmp_list_t kmp_list; /**< Ongoing KMP negotiations */
kmp_addr_t *addr; /**< EUI-64 (Relay IP address, Relay port) */
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 */

View File

@ -35,6 +35,7 @@
#define PAE_NVM_NW_INFO_TAG 1
#define PAE_NVM_KEYS_TAG 2
#define PAE_NVM_FRAME_COUNTER_TAG 3
// pan_id (2) + network name (33) + (GTK set (1) + GTK lifetime (4) + GTK (16)) * 4
#define PAE_NVM_NW_INFO_LEN 2 + 33 + (1 + 4 + GTK_LEN) * GTK_NUM
@ -42,12 +43,17 @@
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK (48)
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + PMK_LEN + 8 + 1 + PTK_LEN
nvm_tlv_entry_t *ws_pae_nvm_store_nw_info_tlv_create(uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
// GTK hash (8), frame counter (4), index (1)
#define PAE_NVM_FRAME_COUNTER_LEN 8 + 4 + 1
nvm_tlv_entry_t *ws_pae_buffer_allocate(void)
{
//Allocate worts case buffer
return ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + PAE_NVM_NW_INFO_LEN);
}
void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
{
nvm_tlv_entry_t *tlv_entry = ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + PAE_NVM_NW_INFO_LEN);
if (!tlv_entry) {
return NULL;
}
tlv_entry->tag = PAE_NVM_NW_INFO_TAG;
tlv_entry->len = PAE_NVM_NW_INFO_LEN;
@ -78,7 +84,6 @@ nvm_tlv_entry_t *ws_pae_nvm_store_nw_info_tlv_create(uint16_t pan_id, char *nw_n
tr_debug("NVM NW_INFO write PAN ID %i name: %s", pan_id, nw_name);
return tlv_entry;
}
int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
@ -117,13 +122,8 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *p
return 0;
}
nvm_tlv_entry_t *ws_pae_nvm_store_keys_tlv_create(sec_prot_keys_t *sec_keys)
void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys)
{
nvm_tlv_entry_t *tlv_entry = ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + PAE_NVM_KEYS_LEN);
if (!tlv_entry) {
return NULL;
}
tlv_entry->tag = PAE_NVM_KEYS_TAG;
tlv_entry->len = PAE_NVM_KEYS_LEN;
@ -164,7 +164,6 @@ nvm_tlv_entry_t *ws_pae_nvm_store_keys_tlv_create(sec_prot_keys_t *sec_keys)
tr_debug("NVM KEYS write");
return tlv_entry;
}
int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys)
@ -209,5 +208,44 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
return 0;
}
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, uint8_t index, uint8_t *hash, uint32_t frame_counter)
{
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
memcpy(tlv, hash, GTK_HASH_LEN);
tlv += GTK_HASH_LEN;
tlv = common_write_32_bit(frame_counter, tlv);
*tlv = index;
tr_debug("NVM FRAME COUNTER write");
}
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, uint8_t *index, uint8_t *hash, uint32_t *frame_counter)
{
if (!tlv_entry || !frame_counter) {
return -1;
}
if (tlv_entry->tag != PAE_NVM_FRAME_COUNTER_TAG || tlv_entry->len != PAE_NVM_FRAME_COUNTER_LEN) {
return -1;
}
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
memcpy(hash, tlv, GTK_HASH_LEN);
tlv += GTK_HASH_LEN;
*frame_counter = common_read_32_bit(tlv);
tlv += 4;
*index = *tlv;
tr_debug("NVM FRAME COUNTER read");
return 0;
}
#endif /* HAVE_WS */

View File

@ -27,6 +27,7 @@
/**
* ws_pae_nvm_store_nw_info_tlv_create create NVM network info TLV
*
* \param tlv_entry TLV entry pointer
* \param pan_id PAN ID
* \param nw_name network name
* \param gtks GTK keys
@ -34,7 +35,7 @@
* \return TLV entry or NULL
*
*/
nvm_tlv_entry_t *ws_pae_nvm_store_nw_info_tlv_create(uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks);
void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks);
/**
* ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV
@ -53,12 +54,11 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *p
/**
* ws_pae_nvm_store_keys_tlv_create create NVM keys TLV
*
* \param tlv_entry TLV entry buffer pointer
* \param sec_keys security keys
*
* \return TLV entry or NULL
*
*/
nvm_tlv_entry_t *ws_pae_nvm_store_keys_tlv_create(sec_prot_keys_t *sec_keys);
void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys);
/**
* ws_pae_nvm_store_nw_info_tlv_read read from NVM keys TLV
@ -72,4 +72,32 @@ nvm_tlv_entry_t *ws_pae_nvm_store_keys_tlv_create(sec_prot_keys_t *sec_keys);
*/
int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys);
/**
* ws_pae_nvm_store_frame_counter_tlv_create create NVM frame counter TLV
*
* \param tlv_entry TLV entry buffer pointer
* \param index index
* \param hash hash
* \param frame_counter frame counter
*
*
*/
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, uint8_t index, uint8_t *hash, uint32_t frame_counter);
/**
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV
*
* \param tlv_entry TLV entry
* \param index index
* \param hash hash
* \param frame_counter frame counter
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, uint8_t *index, uint8_t *hash, uint32_t *frame_counter);
nvm_tlv_entry_t *ws_pae_buffer_allocate(void);
#endif /* WS_PAE_NVM_DATA_H_ */

View File

@ -193,6 +193,10 @@ static int8_t ws_pae_nvm_store_read(const char *file_name, nvm_tlv_list_t *tlv_l
fclose(fp);
if (failure) {
ns_list_foreach_safe(nvm_tlv_entry_t, entry, tlv_list) {
ns_list_remove(tlv_list, entry);
ns_dyn_mem_free(entry);
}
tr_error("NVM read error %s", file_name);
return PAE_NVM_FILE_READ_ERROR;
} else {

View File

@ -27,7 +27,12 @@
// tag + length
#define NVM_TLV_FIXED_LEN 4
typedef struct {
// file names
#define NW_INFO_FILE_NAME "pae_nw_info"
#define KEYS_FILE_NAME "pae_keys"
#define FRAME_COUNTER_FILE_NAME "pae_frame_counter"
typedef struct nvm_tlv_entry {
ns_list_link_t link; /**< Link */
uint16_t tag; /**< Unique tag */
uint16_t len; /**< Number of the bytes after the length field */

View File

@ -73,9 +73,6 @@
#define INITIAL_KEY_TIMER_MIN 3
#define INITIAL_KEY_TIMER_MAX 30
const char *NW_INFO_FILE = "pae_nw_info";
const char *KEYS_FILE = "pae_keys";
typedef struct {
char network_name[33]; /**< Network name for keys */
sec_prot_gtk_keys_t *gtks; /**< Link to GTKs */
@ -106,6 +103,7 @@ typedef struct {
bool timer_running : 1; /**< Timer is running */
bool new_br_eui_64_set : 1; /**< Border router address has been set */
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
bool entry_address_active: 1;
} pae_supp_t;
@ -151,6 +149,9 @@ static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
.receive = kmp_eapol_pdu_if_receive
};
static const char *NW_INFO_FILE = NW_INFO_FILE_NAME;
static const char *KEYS_FILE = KEYS_FILE_NAME;
static int8_t tasklet_id = -1;
static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link);
@ -185,7 +186,8 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,
// Stores target/parent address
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64);
// Sets target address in use
pae_supp->entry.addr = (kmp_addr_t *) &pae_supp->target_addr;
pae_supp->entry.addr = pae_supp->target_addr;
pae_supp->entry_address_active = true;
pae_supp->auth_requested = true;
@ -326,7 +328,6 @@ int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interfac
}
if (sec_prot_keys_gtk_status_active_set(&pae_supp->gtks, index) >= 0) {
tr_info("NW send key index set: %i", index + 1);
pae_supp->nw_key_index_set(interface_ptr, index);
} else {
tr_info("NW send key index: %i, no changes", index + 1);
@ -349,21 +350,26 @@ static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
ws_pae_supp_nvm_keys_write(pae_supp);
sec_prot_keys_updated_reset(&pae_supp->entry.sec_keys);
}
}
static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp)
{
nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
if (!tlv_entry) {
return -1;
}
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
nvm_tlv_entry_t *tlv_entry = ws_pae_nvm_store_nw_info_tlv_create(pae_supp->sec_keys_nw_info.key_pan_id,
pae_supp->sec_keys_nw_info.network_name,
&pae_supp->gtks);
ws_pae_nvm_store_nw_info_tlv_create(tlv_entry, pae_supp->sec_keys_nw_info.key_pan_id,
pae_supp->sec_keys_nw_info.network_name,
&pae_supp->gtks);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, &tlv_list);
ns_list_remove(&tlv_list, tlv_entry);
ns_dyn_mem_free(tlv_entry);
return 0;
}
@ -388,15 +394,18 @@ static int8_t ws_pae_supp_nvm_nw_info_read(pae_supp_t *pae_supp)
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp)
{
nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
if (!tlv_entry) {
return -1;
}
nvm_tlv_list_t tlv_list;
ns_list_init(&tlv_list);
nvm_tlv_entry_t *tlv_entry = ws_pae_nvm_store_keys_tlv_create(&pae_supp->entry.sec_keys);
ws_pae_nvm_store_keys_tlv_create(tlv_entry, &pae_supp->entry.sec_keys);
ns_list_add_to_end(&tlv_list, tlv_entry);
ws_pae_nvm_store_tlv_file_write(KEYS_FILE, &tlv_list);
ns_list_remove(&tlv_list, tlv_entry);
ns_dyn_mem_free(tlv_entry);
return 0;
}
@ -438,7 +447,7 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
// Stores target/parent address
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, parent_eui_64);
// Sets parent address in use
pae_supp->entry.addr = (kmp_addr_t *) &pae_supp->target_addr;
pae_supp->entry.addr = pae_supp->target_addr;
ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_REAUTHENTICATION_TICKS);
tr_info("PAE wait for auth seconds: %i", WAIT_FOR_REAUTHENTICATION_TICKS / 10);
@ -449,9 +458,9 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
return -1;
}
tr_info("EAPOL target: %s", trace_array(kmp_address_eui_64_get(pae_supp->entry.addr), 8));
tr_info("EAPOL target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
kmp_api_create_request(kmp, IEEE_802_1X_MKA_KEY, pae_supp->entry.addr, &pae_supp->entry.sec_keys);
kmp_api_create_request(kmp, IEEE_802_1X_MKA_KEY, &pae_supp->entry.addr, &pae_supp->entry.sec_keys);
return 0;
}
@ -735,8 +744,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
tr_debug("PAE idle");
// Sets target/parent address to null
pae_supp->entry.addr = NULL;
pae_supp->entry_address_active = false;
// If not already completed, restart bootstrap
ws_pae_supp_authenticate_response(pae_supp, false);
@ -846,8 +854,8 @@ static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_
}
// Message from EAPOL target node, route to self
if (pae_supp->entry.addr) {
if (memcmp(eui_64, kmp_address_eui_64_get(pae_supp->entry.addr), 8) == 0) {
if (pae_supp->entry_address_active) {
if (memcmp(eui_64, pae_supp->entry.addr.eui_64, 8) == 0) {
return 0;
}
}
@ -945,7 +953,7 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
return NULL;
}
if (!pae_supp->entry.addr) {
if (!pae_supp->entry_address_active) {
// Does no longer wait for authentication, ignores message
return NULL;
}
@ -954,7 +962,7 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
pae_supp->auth_trickle_running = false;
// Updates parent address
kmp_address_copy(pae_supp->entry.addr, addr);
kmp_address_copy(&pae_supp->entry.addr, addr);
// Check if ongoing
kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
@ -991,7 +999,7 @@ static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_t
}
// Updates parent address
kmp_api_addr_set(kmp, pae_supp->entry.addr);
kmp_api_addr_set(kmp, &pae_supp->entry.addr);
// Sets security keys to KMP
kmp_api_sec_keys_set(kmp, &pae_supp->entry.sec_keys);

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018-2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_stats.h"
#include "6LoWPAN/ws/ws_common.h"
#include "ws_management_api.h"
#define TRACE_GROUP "wsst"
#ifdef HAVE_WS
int ws_statistics_start(int8_t interface_id, ws_statistics_t *stats_ptr)
{
if (!stats_ptr) {
return -1;
}
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !ws_info(cur)) {
return -1;
}
cur->ws_info->stored_stats_ptr = stats_ptr;
return 0;
}
int ws_statistics_stop(int8_t interface_id)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !ws_info(cur)) {
return -1;
}
cur->ws_info->stored_stats_ptr = NULL;
return 0;
}
void ws_stats_update(protocol_interface_info_entry_t *cur, ws_stats_type_t type, uint32_t update_val)
{
if (!cur || !ws_info(cur)) {
return;
}
ws_statistics_t *stored_stats = cur->ws_info->stored_stats_ptr;
if (stored_stats) {
switch (type) {
case STATS_WS_ASYNCH_TX:
stored_stats->asynch_tx_count += update_val;
break;
case STATS_WS_ASYNCH_RX:
stored_stats->asynch_rx_count += update_val;
break;
}
}
}
#endif // HAVE_WS

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2018-2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WS_STATS_H_
#define WS_STATS_H_
#ifdef HAVE_WS
typedef enum {
STATS_WS_ASYNCH_TX,
STATS_WS_ASYNCH_RX
} ws_stats_type_t;
void ws_stats_update(protocol_interface_info_entry_t *cur, ws_stats_type_t type, uint32_t update_val);
#endif // HAVE_WS
#endif // WS_STATS_H_

View File

@ -1037,10 +1037,7 @@ buffer_t *icmpv6_up(buffer_t *buf)
cur = buf->interface;
if (buf->options.ll_security_bypass_rx) {
tr_debug("ICMP: Drop by EP");
goto drop;
}
if (data_len < 4) {
//tr_debug("Ic1");
@ -1051,6 +1048,13 @@ buffer_t *icmpv6_up(buffer_t *buf)
buf->options.type = *dptr++;
buf->options.code = *dptr++;
if (buf->options.ll_security_bypass_rx) {
if (!ws_info(buf->interface) || !(buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL && buf->options.code == ICMPV6_CODE_RPL_DIS)) {
//tr_debug("ICMP: Drop by EP");
goto drop;
}
}
/* Check FCS first */
if (buffer_ipv6_fcf(buf, IPV6_NH_ICMPV6)) {
tr_warn("ICMP cksum error!");
@ -1369,6 +1373,21 @@ void ack_remove_neighbour_cb(struct buffer *buffer_ptr, uint8_t status)
}
static void icmpv6_aro_cb(buffer_t *buf, uint8_t status)
{
uint8_t ll_address[16];
if (buf->dst_sa.addr_type == ADDR_IPV6) {
/*Full IPv6 address*/
memcpy(ll_address, buf->dst_sa.address, 16);
} else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
// Build link local address from long MAC address
memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_address + 8, &buf->dst_sa.address[2], 8);
ll_address[8] ^= 2;
}
rpl_control_address_register_done(buf->interface, ll_address, status);
}
buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16], const uint8_t *prompting_src_addr, bool unicast, bool unspecified_source, const aro_t *aro)
{
if (!cur || addr_is_ipv6_multicast(target_addr)) {
@ -1444,7 +1463,7 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
/* If ARO Success sending is omitted, MAC ACK is used instead */
/* Setting callback for receiving ACK from adaptation layer */
if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) {
buf->ack_receive_cb = rpl_control_address_register_done;
buf->ack_receive_cb = icmpv6_aro_cb;
}
}
if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) {
@ -1677,6 +1696,10 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
}
if (ws_info(cur) && aro && aro->status != ARO_SUCCESS) {
/*If Aro failed we will kill the neigbour after we have succeeded in sending message*/
if (!ws_common_negative_aro_mark(cur, aro->eui64)) {
tr_debug("Neighbour removed for negative response send");
return buffer_free(buf);
}
buf->ack_receive_cb = ack_remove_neighbour_cb;
}

View File

@ -96,8 +96,6 @@ typedef struct if_address_entry {
bool temporary: 1; // RFC 4941 temporary address
bool tentative: 1; // Tentative address (Duplicate Address Detection running)
bool group_added: 1; // Solicited-Node group added
uint8_t addr_reg_pend; // Bitmask for pending address registrations. Based on RPL path control bits
uint8_t addr_reg_done; // Bitmask for address registration done. Based on RPL path control bits
if_address_source_t source; //
if_address_callback_fn *cb; // Address protocol callback function
void *data; // Address protocol data

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file ns_monitor.h
* \brief Utility functions concerning IPv6 stack monitoring.
*
* Module can monitor nanostack heap usage and release memory if heap usage is too high.
* Mmeory monitoring can work if memory statistics are enabled in nsdynmemLIB.
*
*/
#ifndef _NS_MONITOR_H
#define _NS_MONITOR_H
int ns_monitor_init(void);
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);
#endif // _NS_MONITOR_H

View File

@ -865,7 +865,6 @@ void addr_fast_timer(protocol_interface_info_entry_t *cur, uint_fast16_t ticks)
}
#endif
} else {
addr->addr_reg_done = 0;
addr_cb(cur, addr, ADDR_CALLBACK_TIMER);
}

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file ns_monitor.c
* \brief Utility functions for nanostack maintenance
*
* This module tracks stack current heap usage and triggers GC if heap usage is too high.
* GC is triggered by:
* 1. Heap usage is above HEAP_USAGE_HIGH
* 2. Heap usage is above HEAP_USAGE_CRITICAL
* 3. If nsdynmemLIB memory allocation has failed since last check
*/
#include "nsconfig.h"
#include "ns_types.h"
#define HAVE_DEBUG
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "ipv6_stack/ipv6_routing_table.h"
#include "NWK_INTERFACE/Include/protocol.h"
#define TRACE_GROUP "mntr"
typedef enum {
NS_MONITOR_STATE_HEAP_GC_IDLE = 0,
NS_MONITOR_STATE_HEAP_GC_HIGH,
NS_MONITOR_STATE_GC_CRITICAL
} ns_monitor_state_e;
#define HEAP_HIGH_WATERWARK (0.95) /* Heap usage HIGH threshold */
#define HEAP_CRITICAL_WATERMARK (0.99) /* Heap usage CRITICAL threshold */
#define NS_MAINTENANCE_TIMER_INTERVAL 10 // Maintenance interval
typedef struct ns_monitor__s {
ns_mem_heap_size_t heap_high_watermark;
ns_mem_heap_size_t heap_critical_watermark;
uint32_t prev_heap_alloc_fail_cnt;
ns_monitor_state_e ns_monitor_heap_gc_state;
const mem_stat_t *mem_stats;
uint16_t ns_maintenance_timer;
} ns_monitor_t;
static ns_monitor_t *ns_monitor_ptr = NULL;
typedef void (ns_maintenance_gc_cb)(bool full_gc);
/*
* Garbage collection functions.
* Add more GC performing functions to the table
*
*/
static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = {
ipv6_destination_cache_forced_gc
};
static void ns_monitor_heap_gc(bool full_gc)
{
(void) full_gc;
for (unsigned int i = 0; i < sizeof(ns_maintenance_gc_functions) / sizeof(ns_maintenance_gc_functions[0]); i++) {
if (ns_maintenance_gc_functions[i]) {
(ns_maintenance_gc_functions[i])(full_gc);
}
}
}
static void ns_monitor_periodic_heap_health_check(void)
{
if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes > ns_monitor_ptr->heap_critical_watermark) {
// Heap usage above CRITICAL
if (ns_monitor_ptr->ns_monitor_heap_gc_state != NS_MONITOR_STATE_GC_CRITICAL) {
ns_mem_heap_size_t prev_heap_sector_allocated_bytes = ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes;
tr_debug("heap %lu/%lu", (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
ns_monitor_heap_gc(true);
ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_GC_CRITICAL;
tr_info("Stack GC critical: freed %lu bytes", (unsigned long)(prev_heap_sector_allocated_bytes - ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes));
}
} else if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes > ns_monitor_ptr->heap_high_watermark) {
// Heap usage above HIGH
if (ns_monitor_ptr->ns_monitor_heap_gc_state == NS_MONITOR_STATE_HEAP_GC_IDLE) {
ns_mem_heap_size_t prev_heap_sector_allocated_bytes = ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes;
tr_debug("heap %lu/%lu", (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
ns_monitor_heap_gc(false);
ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_HIGH;
tr_info("Stack GC high: freed %lu bytes", (unsigned long)(prev_heap_sector_allocated_bytes - ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes));
}
} else if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes <= ns_monitor_ptr->heap_high_watermark) {
// Heap usage in normal range
ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_IDLE;
}
}
void ns_monitor_timer(uint16_t seconds)
{
if (ns_monitor_ptr) {
ns_monitor_ptr->ns_maintenance_timer += seconds;
if (ns_monitor_ptr->mem_stats->heap_alloc_fail_cnt > ns_monitor_ptr->prev_heap_alloc_fail_cnt) {
// Heap allocation failure occurred since last check
ns_monitor_ptr->prev_heap_alloc_fail_cnt = ns_monitor_ptr->mem_stats->heap_alloc_fail_cnt;
if (ns_monitor_ptr->ns_monitor_heap_gc_state != NS_MONITOR_STATE_GC_CRITICAL) {
ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_GC_CRITICAL;
ns_monitor_heap_gc(true);
ns_monitor_ptr->ns_maintenance_timer = 0;
}
}
if (ns_monitor_ptr->ns_maintenance_timer >= NS_MAINTENANCE_TIMER_INTERVAL) {
ns_monitor_ptr->ns_maintenance_timer -= NS_MAINTENANCE_TIMER_INTERVAL;
ns_monitor_periodic_heap_health_check();
}
}
}
int ns_monitor_init(void)
{
if (ns_monitor_ptr || !ns_dyn_mem_get_mem_stat()) {
// already initialized or memory statistics not available
return -2;
}
ns_monitor_ptr = ns_dyn_mem_alloc(sizeof(ns_monitor_t));
if (ns_monitor_ptr) {
ns_monitor_ptr->mem_stats = ns_dyn_mem_get_mem_stat();
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size * HEAP_HIGH_WATERWARK;
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size * HEAP_CRITICAL_WATERMARK;
ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_IDLE;
ns_monitor_ptr->ns_maintenance_timer = 0;
ns_monitor_ptr->prev_heap_alloc_fail_cnt = 0;
return 0;
}
return -1;
}
int ns_monitor_clear(void)
{
if (ns_monitor_ptr) {
ns_dyn_mem_free(ns_monitor_ptr);
ns_monitor_ptr = NULL;
return 0;
}
return -1;
}
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
{
if (ns_monitor_ptr && (percentage_critical <= 100) && (percentage_high < percentage_critical)) {
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size * percentage_high / 100;
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size * percentage_critical / 100;
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);
return 0;
}
return -1;
}

View File

@ -147,6 +147,11 @@ int DHCPV6_server_service_request_handler(uint16_t instance_id, uint32_t msg_tr_
replyPacket.T1 = dhcp_ia_non_temporal_params.T1;
replyPacket.iaId = dhcp_ia_non_temporal_params.iaId;
replyPacket.transaction_ID = msg_tr_id;
uint16_t duid_length = libdhcpv6_duid_option_size(replyPacket.clientDUID.linkType);
duid_length -= 8;
tr_debug("Response dhcp sol %s clientDUID", trace_array(replyPacket.clientDUID.linkID, duid_length));
//Check First Current list
if (DHCPv6_server_respond_client(serverBase, &replyPacket, &dhcp_ia_non_temporal_params, &responseBuf, true) == 0) {
//Respond

View File

@ -100,7 +100,7 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
int dhcp_client_server_address_update(int8_t interface, uint8_t prefix[static 16], uint8_t server_address[static 16]);
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16]);

View File

@ -96,7 +96,7 @@ void dhcp_client_delete(int8_t interface)
{
protocol_interface_info_entry_t *cur = NULL;
dhcpv6_client_server_data_t *srv_data_ptr;
uint8_t temporary_address[16];
dhcp_service_delete(dhcp_client.service_instance);
@ -110,9 +110,11 @@ void dhcp_client_delete(int8_t interface)
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance);
if (srv_data_ptr != NULL) {
tr_debug("Free DHCPv6 Client\n");
memcpy(temporary_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, 16);
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
addr_delete(cur, temporary_address);
}
} while (srv_data_ptr != NULL);
dhcp_client.service_instance = 0;
@ -234,6 +236,9 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
dhcpv6_renew(protocol_stack_interface_info_get_by_id(interface), NULL, ADDR_CALLBACK_TIMER);
}
return 0;
} else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
//DHCP server address OK
return 0;
}
}
return -1;
@ -302,7 +307,7 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
return 0;
}
int dhcp_client_server_address_update(int8_t interface, uint8_t prefix[static 16], uint8_t server_address[static 16])
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16])
{
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
@ -446,6 +451,7 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
// Default retry values are modified from specification update to message
dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client.sol_timeout, dhcp_client.sol_max_rt, dhcp_client.sol_max_rc);
}
tr_error("DHCP renew send OK");
}
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)

View File

@ -148,7 +148,6 @@ uint8_t mac_indirect_data_req_handle(mac_pre_parsed_frame_t *buf, protocol_inter
/* If the Ack we sent for the Data Request didn't have frame pending set, we shouldn't transmit - child may have slept */
if (!buf->ack_pendinfg_status) {
//tr_debug("Drop by pending");
if (mac_ptr->indirect_pd_data_request_queue) {
tr_error("Wrongly dropped");
}

View File

@ -74,6 +74,8 @@ static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s
static int8_t mac_tasklet_event_handler = -1;
static uint32_t ns_dyn_mem_rate_limiting_threshold = 0xFFFFFFFF;
/**
* Get PHY time stamp.
*
@ -233,7 +235,6 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
if (!rf_mac_setup->macUpState || rf_mac_setup->scan_active) {
status = MLME_TRX_OFF;
tr_debug("Drop MAC tx packet when mac disabled");
goto verify_status;
}
@ -614,11 +615,6 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
ccm_ptr.data_ptr = (mcps_mac_payload_pointer_get(b) + openPayloadLength);
ccm_ptr.data_len = b->mac_payload_length - openPayloadLength;
if (ccm_process_run(&ccm_ptr) != 0) {
tr_warning("MIC Fail adata %s", trace_array(ccm_ptr.adata_ptr, ccm_ptr.adata_len));
tr_warning("Nonce %s", trace_array(ccm_ptr.exp_nonce, 13));
if (openPayloadLength) {
tr_warning("%s", tr_array(ccm_ptr.data_ptr, ccm_ptr.data_len));
}
return MLME_SECURITY_FAIL;
}
@ -660,7 +656,6 @@ static void mcps_comm_status_indication_generate(uint8_t status, mac_pre_parsed_
static int8_t mac_data_interface_host_accept_data(mcps_data_ind_t *data_ind, protocol_interface_rf_mac_setup_s *rf_mac_setup)
{
if ((data_ind->DstAddrMode == MAC_ADDR_MODE_16_BIT) && (data_ind->DstAddr[0] == 0xff && data_ind->DstAddr[1] == 0xff)) {
tr_debug("Drop Multicast packet");
return -1;
}
@ -686,6 +681,7 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
{
int8_t retval = -1;
uint8_t status;
//allocate Data ind primitiv and parse packet to that
mcps_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(mcps_data_ind_t));
@ -720,7 +716,6 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
}
if (!mac_payload_information_elements_parse(buf)) {
tr_debug("Drop by Paylod IE");
goto DROP_PACKET;
}
data_ind->msduLength = buf->mac_payload_length;
@ -738,7 +733,6 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
if (buf->fcf_dsn.frameVersion == MAC_FRAME_VERSION_2015) {
if (!rf_mac_setup->mac_extension_enabled) {
tr_debug("No Ext reg");
goto DROP_PACKET;
}
mcps_data_ie_list_t ie_list;
@ -900,7 +894,6 @@ static void mac_data_interface_parse_beacon(mac_pre_parsed_frame_t *buf, protoco
}
if (!mac_payload_information_elements_parse(buf)) {
tr_debug("Drop by Paylod IE");
return;
}
@ -921,7 +914,6 @@ static void mac_data_interface_parse_beacon(mac_pre_parsed_frame_t *buf, protoco
if (len < gts_field_length) {
return;
}
// gts_info = ptr;
len -= gts_field_length;
ptr += gts_field_length;
}
@ -976,7 +968,6 @@ static void mac_data_interface_frame_handler(mac_pre_parsed_frame_t *buf)
{
protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr;
if (!rf_mac_setup) {
tr_debug("Drop by no mac class");
mcps_sap_pre_parsed_frame_buffer_free(buf);
return;
}
@ -1081,13 +1072,11 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter
if (buf->fcf_dsn.securityEnabled) {
uint8_t status = mac_data_interface_decrypt_packet(buf, &key);
if (status != MLME_SUCCESS) {
tr_debug("ACK Decrypt fail");
return -1;
}
}
if (buf->mac_payload_length && !mac_payload_information_elements_parse(buf)) {
tr_debug("Drop ACK by Paylod IE");
return -1;
}
@ -2068,6 +2057,12 @@ void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf)
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length)
{
// check that system has enough space to handle the new packet
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
if (ns_dyn_mem_stat && ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_rate_limiting_threshold) {
return NULL;
}
mac_pre_parsed_frame_t *buffer = ns_dyn_mem_temporary_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length);
if (buffer) {
@ -2075,6 +2070,7 @@ mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data
buffer->frameLength = frame_length;
memcpy(mac_header_message_start_pointer(buffer), data_ptr, frame_length);
}
return buffer;
}
@ -2298,3 +2294,15 @@ uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_set
return confirmation.status;
}
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
{
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
if (ns_dyn_mem_stat && free_heap_percentage < 100) {
ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * (100 - free_heap_percentage);
return 0;
}
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* Copyright (c) 2016-2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -216,4 +216,6 @@ int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload);
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */

View File

@ -232,7 +232,6 @@ uint8_t mac_mlme_beacon_req_tx(protocol_interface_rf_mac_setup_s *rf_ptr)
buf->fcf_dsn.DstPanPresents = true;
buf->fcf_dsn.SrcPanPresents = false;
tr_debug("BEA REQ tx");
mcps_sap_pd_req_queue_write(rf_ptr, buf);
return 1;
}
@ -843,7 +842,6 @@ static void mlme_scan_operation(protocol_interface_rf_mac_setup_s *rf_mac_setup)
channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true);
if (channel > 0xff || rf_mac_setup->mac_mlme_scan_resp->ResultListSize == MLME_MAC_RES_SIZE_MAX) {
resp->status = MLME_SUCCESS;
tr_debug("Scan Complete..Halt MAC");
platform_enter_critical();
mac_mlme_mac_radio_disabled(rf_mac_setup);
if (resp->ResultListSize == 0 && rf_mac_setup->scan_type == MAC_ACTIVE_SCAN) {
@ -855,7 +853,6 @@ static void mlme_scan_operation(protocol_interface_rf_mac_setup_s *rf_mac_setup)
platform_exit_critical();
//Scan Confirmation
mac_generic_event_trig(MAC_MLME_SCAN_CONFIRM_HANDLER, rf_mac_setup, false);
tr_debug("Trig confirm");
rf_mac_setup->scan_active = false;
} else {
mac_mlme_scan_init((uint8_t) channel, rf_mac_setup);
@ -987,7 +984,6 @@ static void mac_mlme_free_scan_temporary_data(protocol_interface_rf_mac_setup_s
rf_mac_setup->scan_active = false;
if (rf_mac_setup->mac_mlme_scan_resp) {
mlme_scan_conf_t *r = rf_mac_setup->mac_mlme_scan_resp;
tr_debug("%02x", r->ResultListSize);
if (r->ED_values) {
ns_dyn_mem_free(r->ED_values);
r->ED_values = NULL;
@ -995,12 +991,10 @@ static void mac_mlme_free_scan_temporary_data(protocol_interface_rf_mac_setup_s
uint8_t i = 0;
while (i < r->ResultListSize) {
if (r->PAN_values[i]) {
tr_debug("Free PAN result");
ns_dyn_mem_free(r->PAN_values[i]);
}
i++;
}
tr_debug("Free Response");
ns_dyn_mem_free(rf_mac_setup->mac_mlme_scan_resp);
rf_mac_setup->mac_mlme_scan_resp = NULL;
}
@ -1399,11 +1393,6 @@ static void mac_mlme_start_confirm_handler(protocol_interface_rf_mac_setup_s *rf
static void mac_mlme_scan_confirm_handler(protocol_interface_rf_mac_setup_s *rf_ptr, const mlme_scan_conf_t *conf)
{
if (conf->ScanType == MAC_ACTIVE_SCAN) {
tr_debug("Active Scan Result");
} else if (conf->ScanType == MAC_ED_SCAN_TYPE) {
tr_debug("ED Scan Result");
}
if (rf_ptr->tun_extension_rf_driver) {
virtual_data_req_t scan_conf;
uint8_t buf_temp[2];

View File

@ -487,7 +487,8 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
return 0;
} else {
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING)) {
// Do not update CCA count when CCA_OK is received, PHY_LINK_TX_SUCCESS will update it
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK)) {
/* For PHY_LINK_TX_SUCCESS and PHY_LINK_CCA_FAIL cca_retry must always be > 0.
* PHY_LINK_TX_FAIL either happened during transmission or when waiting Ack -> we must use the CCA count given by PHY.
*/

View File

@ -126,7 +126,7 @@ static void mac_sec_mib_key_device_description_remove_from_list(mlme_key_descrip
*prev = *cur;
} else if (cur->DeviceDescriptorHandle == device_descriptor_handle) {
removed_entry = true;
tr_debug("Remove user %u from key", device_descriptor_handle);
//tr_debug("Remove user %u from key", device_descriptor_handle);
}
prev = cur;
cur++;
@ -244,10 +244,10 @@ int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_de
if (memcmp(device_ptr->ExtAddress, device_descriptor->ExtAddress, 8)) {
//Remove last handles key user's
mac_sec_mib_device_description_remove(rf_mac_setup, atribute_index);
tr_debug("Over write %u, mac16 %x mac64: %s, %"PRIu32, atribute_index, device_ptr->ShortAddress, trace_array(device_ptr->ExtAddress, 8), device_ptr->FrameCounter);
//tr_debug("Over write %u, mac16 %x mac64: %s, %"PRIu32, atribute_index, device_ptr->ShortAddress, trace_array(device_ptr->ExtAddress, 8), device_ptr->FrameCounter);
}
tr_debug("Set %u, mac16 %x mac64: %s, %"PRIu32, atribute_index, device_descriptor->ShortAddress, trace_array(device_descriptor->ExtAddress, 8), device_descriptor->FrameCounter);
//tr_debug("Set %u, mac16 %x mac64: %s, %"PRIu32, atribute_index, device_descriptor->ShortAddress, trace_array(device_descriptor->ExtAddress, 8), device_descriptor->FrameCounter);
*device_ptr = *device_descriptor;
return 0;
@ -485,7 +485,7 @@ void mac_sec_mib_device_description_blacklist(protocol_interface_rf_mac_setup_s
for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) {
descriptor = mac_sec_mib_key_device_description_discover_from_list(&rf_mac_setup->key_description_table[i], device_handle);
if (descriptor) {
tr_debug("Black listed device %u lookup%s", device_handle, trace_array(rf_mac_setup->key_description_table[i].Key, 16));
tr_debug("Black listed device %u", device_handle);
descriptor->Blacklisted = true;
}

View File

@ -699,3 +699,19 @@ void sw_mac_stats_update(protocol_interface_rf_mac_setup_s *setup, mac_stats_typ
}
}
}
uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api)
{
if (!mac_api) {
return 0;
}
// Get a pointer to MAC setup structure
protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_mac_api(mac_api);
if (!mac_setup) {
return 0;
}
uint32_t time_stamp_buffer;
mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)&time_stamp_buffer);
return time_stamp_buffer;
}

View File

@ -515,5 +515,6 @@ extern void protocol_core_dhcpv6_allocated_address_remove(protocol_interface_inf
extern void nwk_bootsrap_state_update(arm_nwk_interface_status_type_e posted_event, protocol_interface_info_entry_t *cur);
void bootsrap_next_state_kick(icmp_state_t new_state, protocol_interface_info_entry_t *cur);
int8_t protocol_interface_address_compare(const uint8_t *addr);
bool protocol_address_prefix_cmp(protocol_interface_info_entry_t *cur, const uint8_t *prefix, uint8_t prefix_len);
bool protocol_interface_any_address_match(const uint8_t *prefix, uint8_t prefix_len);
#endif /* _NS_PROTOCOL_H */

View File

@ -24,6 +24,7 @@
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "Core/include/ns_socket.h"
#include "Core/include/ns_monitor.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "NWK_INTERFACE/Include/protocol_timer.h"
#include "platform/arm_hal_interrupt.h"
@ -175,6 +176,7 @@ void protocol_root_tasklet(arm_event_t *event)
switch (event_type) {
case ARM_LIB_TASKLET_INIT_EVENT:
tr_debug("NS Root task Init");
ns_monitor_init();
break;
case ARM_IN_PROTOCOL_TIMER_EVENT: {
@ -306,8 +308,7 @@ void core_timer_event_handle(uint16_t ticksUpdate)
ws_pae_controller_slow_timer(seconds);
#endif
protocol_6lowpan_mle_timer(seconds);
/* This limit bad behaviour device's MLE link reject generation */
ns_monitor_timer(seconds);
} else {
protocol_core_seconds_timer -= ticksUpdate;
}
@ -387,7 +388,6 @@ void protocol_core_init(void)
protocol_core_timer_info.core_security_ticks_counter = SEC_LIB_X_100MS_COUNTER;
protocol_timer_start(PROTOCOL_TIMER_STACK_TIM, protocol_core_cb, 100);
}
void protocol_core_interface_info_reset(protocol_interface_info_entry_t *entry)
@ -1140,9 +1140,9 @@ int8_t protocol_interface_address_compare(const uint8_t *addr)
return -1;
}
static bool protocol_address_prefix_cmp(protocol_interface_info_entry_t *interface, const uint8_t *prefix, uint8_t prefix_len)
bool protocol_address_prefix_cmp(protocol_interface_info_entry_t *cur, const uint8_t *prefix, uint8_t prefix_len)
{
ns_list_foreach(if_address_entry_t, adr, &interface->ip_addresses) {
ns_list_foreach(if_address_entry_t, adr, &cur->ip_addresses) {
if (bitsequal(adr->address, prefix, prefix_len)) {
/* Prefix stil used at list so stop checking */
return true;

View File

@ -171,68 +171,85 @@ void rpl_control_unpublish_address(rpl_domain_t *domain, const uint8_t addr[16])
}
}
static if_address_entry_t *rpl_instance_reg_addr_get(protocol_interface_info_entry_t *interface)
void rpl_control_request_parent_link_confirmation(bool requested)
{
ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) {
if (!address->addr_reg_done && !addr_is_ipv6_link_local(address->address)) {
return address;
}
}
return NULL;
rpl_policy_set_parent_confirmation_request(requested);
}
/* Send address registration to either specified address, or to non-registered address */
void rpl_control_register_address(protocol_interface_info_entry_t *interface, if_address_entry_t *addr)
void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16])
{
if_address_entry_t *reg_addr = addr;
if (!reg_addr) {
reg_addr = rpl_instance_reg_addr_get(interface);
if (!reg_addr) {
return;
}
if (!rpl_policy_parent_confirmation_requested()) {
return;
}
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
rpl_instance_send_address_registration(interface, instance, reg_addr);
rpl_instance_send_address_registration(instance, addr);
}
}
void rpl_control_address_register_done(struct buffer *buf, uint8_t status)
void rpl_control_address_register_done(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], uint8_t status)
{
ns_list_foreach(if_address_entry_t, addr, &buf->interface->ip_addresses) {
if (!interface->rpl_domain) {
return;
}
if (!rpl_policy_parent_confirmation_requested()) {
return;
}
/* Optimize, ll addresses are not registered anyway.. */
if (addr_is_ipv6_link_local(addr->address) || !addr->addr_reg_pend) {
continue;
}
ns_list_foreach(struct rpl_instance, instance, &buf->interface->rpl_domain->instances) {
if (rpl_instance_address_registration_done(buf->interface, instance, addr, status)) {
return;
}
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id);
if (neighbour) {
rpl_instance_address_registration_done(interface, instance, neighbour, status);
}
}
}
bool rpl_control_is_dodag_parent(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16])
bool rpl_control_is_dodag_parent(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], bool selected)
{
if (!interface->rpl_domain) {
return false;
}
// go through instances and parents and check if they match the address.
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
if (rpl_instance_address_is_parent(instance, ll_addr)) {
if (rpl_instance_address_is_parent(instance, ll_addr, selected)) {
return true;
}
}
return false;
}
uint16_t rpl_control_parent_candidate_list_size(protocol_interface_info_entry_t *interface, bool parent_list)
{
if (!interface->rpl_domain) {
return 0;
}
uint16_t parent_list_size = 0;
// go through instances and parents and check if they match the address.
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
uint16_t current_size = rpl_instance_address_candidate_count(instance, parent_list);
if (current_size > parent_list_size) {
parent_list_size = current_size;
}
}
return parent_list_size;
}
void rpl_control_neighbor_delete(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16])
{
if (!interface->rpl_domain) {
return;
}
// go through instances and delete address.
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
rpl_instance_neighbor_delete(instance, ll_addr);
rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id);
if (neighbour) {
rpl_delete_neighbour(instance, neighbour);
}
}
return;
}
/* Address changes need to trigger DAO target re-evaluation */
@ -686,13 +703,12 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
uint32_t preferred = common_read_32_bit(ptr + 8);
const uint8_t *prefix = ptr + 16;
if (!pref_parent || neighbour == pref_parent) {
if (rpl_upward_accept_prefix_update(dodag, neighbour, pref_parent)) {
/* Store prefixes for possible forwarding */
/* XXX if leaf - don't bother? Or do we want to remember them for
* when we switch DODAG, as mentioned above?
*/
prefix_entry_t *prefix_entry = rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true);
if (prefix_entry && pref_parent) {
rpl_control_process_prefix_option(prefix_entry, cur);
@ -840,7 +856,6 @@ static void rpl_control_dao_trigger_request(rpl_instance_t *instance, rpl_dodag_
static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, rpl_domain_t *domain, buffer_t *buf)
{
if (!rpl_control_options_well_formed_in_buffer(buf, 24)) {
tr_error("DIO format");
malformed:
protocol_stats_update(STATS_RPL_MALFORMED_MESSAGE, 1);
return buffer_free(buf);
@ -993,7 +1008,7 @@ malformed:
rpl_control_process_prefix_options(cur, instance, dodag, neighbour, ptr, buffer_data_end(buf));
rpl_dodag_update_implicit_system_routes(dodag, neighbour);
//rpl_dodag_update_implicit_system_routes(dodag, neighbour);
rpl_control_process_route_options(instance, dodag, version, neighbour, rank, ptr, buffer_data_end(buf));
//rpl_control_process_metric_containers(neighbour, ptr, buffer_data_end(buf))
@ -1137,7 +1152,7 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
} else {
prefix->options &= ~ PIO_R;
if (rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && prefix->lifetime != 0) {
if (rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && (prefix->lifetime != 0 || !(prefix->options & PIO_A))) {
continue;
}
}
@ -1175,7 +1190,7 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
ns_list_foreach_safe(prefix_entry_t, prefix, prefixes) {
/* See equivalent checks in length calculation above */
if ((prefix->options & (PIO_L | RPL_PIO_PUBLISHED)) == PIO_L ||
(!(prefix->options & PIO_R) && rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && prefix->lifetime != 0)) {
(!(prefix->options & PIO_R) && rpl_dodag_mop(dodag) == RPL_MODE_NON_STORING && (prefix->lifetime != 0 || !(prefix->options & PIO_A)))) {
continue;
}
@ -1252,7 +1267,6 @@ void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entr
static buffer_t *rpl_control_dis_handler(protocol_interface_info_entry_t *cur, rpl_domain_t *domain, buffer_t *buf, bool multicast)
{
if (!rpl_control_options_well_formed_in_buffer(buf, 2)) {
tr_error("DIS format");
protocol_stats_update(STATS_RPL_MALFORMED_MESSAGE, 1);
return buffer_free(buf);
}
@ -1380,7 +1394,6 @@ static buffer_t *rpl_control_dao_ack_handler(protocol_interface_info_entry_t *cu
if (buffer_data_length(buf) < 4) {
format_error:
tr_error("DAO-ACK format");
protocol_stats_update(STATS_RPL_MALFORMED_MESSAGE, 1);
return buffer_free(buf);
}
@ -1464,7 +1477,6 @@ static buffer_t *rpl_control_dao_handler(protocol_interface_info_entry_t *cur, r
{
if (buffer_data_length(buf) < 4) {
format_error:
tr_error("DAO format");
protocol_stats_update(STATS_RPL_MALFORMED_MESSAGE, 1);
return buffer_free(buf);
}

View File

@ -147,10 +147,13 @@ void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callba
/* Target publishing */
void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime);
void rpl_control_unpublish_address(rpl_domain_t *domain, const uint8_t addr[16]);
void rpl_control_register_address(struct protocol_interface_info_entry *interface, if_address_entry_t *addr);
void rpl_control_address_register_done(struct buffer *buf, uint8_t status);
bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], bool selected);
uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list);
void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
/* Parent link confirmation API extension */
void rpl_control_request_parent_link_confirmation(bool requested);
void rpl_control_register_address(struct protocol_interface_info_entry *interface, const uint8_t addr[16]);
void rpl_control_address_register_done(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t status);
/* Configure and return the routing lookup predicate for a specified RPL instance ID */
ipv6_route_predicate_fn_t *rpl_control_get_route_predicate(rpl_domain_t *domain, uint8_t instance_id, const uint8_t src[16], const uint8_t dst[16]);
@ -172,7 +175,7 @@ uint16_t rpl_control_current_rank(const struct rpl_instance *instance);
#define rpl_control_slow_timer(seconds) ((void) 0)
#define rpl_control_remove_domain_from_interface(cur) ((void) 0)
#define rpl_control_register_address(interface, addr) ((void) 0)
#define rpl_control_address_register_done NULL
#define rpl_control_address_register_done(interface, ll_addr, status) ((void) 0)
#endif /* HAVE_RPL */

View File

@ -372,6 +372,12 @@ void rpl_instance_publish_dao_target(rpl_instance_t *instance, const uint8_t *pr
target->descriptor_present = want_descriptor;
target->descriptor = descriptor;
target->path_control = 0xFF; /* Use as much path control as we can (PCS limits) */
target->response_wait_time = 0;
target->active_confirmation_state = false;
target->trig_confirmation_state = true;
//Activate allways registration
instance->pending_neighbour_confirmation = rpl_policy_parent_confirmation_requested();
tr_debug("New Target %s", trace_ipv6(target->prefix));
/* Path lifetime left as 0 for now - will be filled in on transmission, along with refresh timer */
rpl_instance_dao_trigger(instance, 0);
}
@ -383,7 +389,7 @@ void rpl_instance_dao_trigger(rpl_instance_t *instance, uint16_t delay)
}
if (instance->delay_dao_timer == 0 || instance->delay_dao_timer > delay) {
instance->delay_dao_timer = delay;
tr_debug("DAO trigger %" PRIu16, delay);
//tr_debug("DAO trigger %" PRIu16, delay);
}
}
@ -583,63 +589,63 @@ static void rpl_downward_reset_assigning(rpl_instance_t *instance, uint8_t pcs_m
}
}
void rpl_instance_send_address_registration(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, if_address_entry_t *addr)
static void rpl_instance_unconfirm_parent_info(rpl_instance_t *instance)
{
aro_t aro;
buffer_t *buf;
aro.status = ARO_SUCCESS;
aro.present = true;
aro.lifetime = (addr->valid_lifetime / 60) + 1;
memcpy(aro.eui64, interface->mac, 8);
// go through neighbour list, and send to all assigned parents.
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
if (neighbour->dao_path_control) {
tr_debug("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address));
buf = icmpv6_build_ns(interface, neighbour->ll_address, addr->address, true, false, &aro);
addr->addr_reg_pend |= neighbour->dao_path_control;
protocol_push(buf);
} else {
tr_debug("Skip ARO to %s - no pc", trace_ipv6(neighbour->ll_address));
}
}
}
bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, if_address_entry_t *addr, uint8_t status)
{
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
// Check path control mask
if (!(addr->addr_reg_pend & neighbour->dao_path_control)) {
ns_list_foreach_safe(rpl_neighbour_t, n, &instance->candidate_neighbours) {
if (n->dao_path_control == 0) {
continue;
}
n->confirmed = false;
tr_debug("Address %s register to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address));
/* Clear pending flag */
addr->addr_reg_pend &= ~neighbour->dao_path_control;
if (status == SOCKET_TX_DONE) {
addr->addr_reg_done |= neighbour->dao_path_control;
/* State_timer is 1/10 s. Set renewal to 75-85% of lifetime */
addr->state_timer = (addr->preferred_lifetime * randLIB_get_random_in_range(75, 85) / 10);
} else {
tr_error("Address registration failed");
rpl_delete_neighbour(instance, neighbour);
}
/* If that was last one to reply, send next one. */
if (!addr->addr_reg_pend) {
rpl_control_register_address(interface, NULL);
}
return true;
}
return false;
}
static rpl_dao_target_t *rpl_instance_get_pending_target_confirmation_for_address(rpl_instance_t *instance, const uint8_t address[16])
{
ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) {
if (memcmp(n->prefix, address, 16) == 0) {
return n;
}
}
return NULL;
}
static rpl_dao_target_t *rpl_instance_get_pending_target_confirmation(rpl_instance_t *instance)
{
ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) {
if (!n->trig_confirmation_state) {
continue;
}
n->trig_confirmation_state = false;
n->active_confirmation_state = true;
instance->wait_response = NULL;
rpl_instance_unconfirm_parent_info(instance);
return n;
}
return NULL;
}
void rpl_instance_send_address_registration(rpl_instance_t *instance, const uint8_t addr[16])
{
if (addr) {
rpl_dao_target_t *target = rpl_instance_get_pending_target_confirmation_for_address(instance, addr);
if (!target) {
return;
}
if (instance->pending_neighbour_confirmation && (target->active_confirmation_state || target->trig_confirmation_state)) {
return;
}
target->trig_confirmation_state = true;
} else if (!instance->pending_neighbour_confirmation) {
ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) {
n->trig_confirmation_state = true;
}
}
instance->pending_neighbour_confirmation = true;
}
/* We are optimised for sending updates to existing targets to current parents;
* we track the state of what information DAO parents have, and manage the
* updates together with message coalescing and ack tracking.
@ -673,6 +679,12 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance)
return;
}
//Verify that no pending address registartion to parent
if (instance->pending_neighbour_confirmation) {
rpl_instance_dao_trigger(instance, 6 * 10);
return;
}
if (instance->dao_in_transit) {
// Force current DAO timeout to be cut short, then
// when it times out, it will re-evaluate the situation,
@ -1689,4 +1701,145 @@ void rpl_downward_print_instance(rpl_instance_t *instance, route_print_fn_t *pri
}
}
rpl_dao_target_t *rpl_instance_get_active_target_confirmation(rpl_instance_t *instance)
{
ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) {
if (!n->active_confirmation_state) {
continue;
}
return n;
}
return NULL;
}
static rpl_neighbour_t *rpl_instance_get_unconfirmed_parent_info(rpl_instance_t *instance)
{
ns_list_foreach_safe(rpl_neighbour_t, n, &instance->candidate_neighbours) {
if (n->dao_path_control != 0 && !n->confirmed) {
return n;
}
}
return NULL;
}
static bool rpl_instance_push_address_registration(protocol_interface_info_entry_t *interface, rpl_neighbour_t *neighbour, if_address_entry_t *addr)
{
aro_t aro;
aro.status = ARO_SUCCESS;
aro.present = true;
aro.lifetime = (addr->valid_lifetime / 60) + 1;
memcpy(aro.eui64, interface->mac, 8);
buffer_t *buf = icmpv6_build_ns(interface, neighbour->ll_address, addr->address, true, false, &aro);
if (!buf) {
return false;
}
tr_debug("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address));
protocol_push(buf);
return true;
}
static if_address_entry_t *rpl_interface_addr_get(protocol_interface_info_entry_t *interface, const uint8_t addr[16])
{
ns_list_foreach(if_address_entry_t, entry, &interface->ip_addresses) {
if (memcmp(entry->address, addr, 16) == 0) {
return entry;
}
}
return NULL;
}
void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint16_t seconds)
{
if (!instance->pending_neighbour_confirmation) {
return; //No need validate any confirmation
}
//Get Pendig active target
rpl_dao_target_t *dao_target = rpl_instance_get_active_target_confirmation(instance);
if (!dao_target) {
dao_target = rpl_instance_get_pending_target_confirmation(instance);
if (!dao_target) {
instance->pending_neighbour_confirmation = false;
return;
}
tr_debug("Register Address to parent %s", trace_ipv6(dao_target->prefix));
}
if (instance->wait_response) {
uint16_t wait_time = dao_target->response_wait_time;
if (seconds < wait_time) {
//Must Wait response time untill finish
dao_target->response_wait_time -= seconds;
return;
}
dao_target->response_wait_time = 0;
instance->wait_response = NULL;
}
//Get Next Parent for confirmation
rpl_neighbour_t *neighbour = rpl_instance_get_unconfirmed_parent_info(instance);
if (!neighbour) {
dao_target->active_confirmation_state = false;
return;
}
//Get address and buffer
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(neighbour->interface_id);
if (!interface) {
dao_target->response_wait_time = 0;
instance->wait_response = NULL;
dao_target->active_confirmation_state = false;
return;
}
if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix);
if (!address) {
dao_target->response_wait_time = 0;
instance->wait_response = NULL;
dao_target->active_confirmation_state = false;
return;
}
if (rpl_instance_push_address_registration(interface, neighbour, address)) {
instance->wait_response = neighbour;
dao_target->response_wait_time = 5;
}
}
void rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status)
{
if (!instance->pending_neighbour_confirmation) {
return;
}
rpl_dao_target_t *dao_target = rpl_instance_get_active_target_confirmation(instance);
if (!dao_target || instance->wait_response != neighbour) {
return;
}
tr_debug("Address %s register to %s", trace_ipv6(dao_target->prefix), trace_ipv6(neighbour->ll_address));
if (status == SOCKET_TX_DONE) {
/* State_timer is 1/10 s. Set renewal to 75-85% of lifetime */
if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix);
if (address) {
address->state_timer = (address->preferred_lifetime * randLIB_get_random_in_range(75, 85) / 10);
}
neighbour->confirmed = true;
dao_target->response_wait_time = 6;
} else {
tr_error("Address registration failed");
rpl_delete_neighbour(instance, neighbour);
}
}
#endif /* HAVE_RPL */

View File

@ -40,9 +40,10 @@ struct rpl_dao_target *rpl_instance_match_dao_target(struct rpl_instance *instan
void rpl_instance_dao_request(struct rpl_instance *instance, struct rpl_neighbour *neighbour);
void rpl_instance_dao_trigger(struct rpl_instance *instance, uint16_t delay);
void rpl_instance_dao_acked(struct rpl_instance *instance, const uint8_t src[16], int8_t interface_id, uint8_t dao_sequence, uint8_t status);
void rpl_instance_send_address_registration(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, if_address_entry_t *addr);
bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, if_address_entry_t *addr, uint8_t status);
void rpl_instance_parent_address_reg_timer_update(struct rpl_instance *instance, uint16_t seconds);
void rpl_instance_send_address_registration(rpl_instance_t *instance, const uint8_t addr[16]);
void rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status);
struct rpl_dao_target *rpl_instance_get_active_target_confirmation(struct rpl_instance *instance);
#ifdef HAVE_RPL_DAO_HANDLING
bool rpl_instance_dao_received(struct rpl_instance *instance, const uint8_t src[16], int8_t interface_id, bool multicast, const uint8_t *opts, uint16_t opts_len, uint8_t *status_out);

View File

@ -34,6 +34,8 @@
#define TRACE_GROUP "RPLy"
static bool rpl_policy_parent_confirmation_req = false;
/* TODO - application API to control when to join new instances / DODAGs
*
* Eg, allow application to ignore local DODAGs, or specify known instance IDs,
@ -318,6 +320,17 @@ uint16_t rpl_policy_mrhof_parent_switch_threshold(const rpl_domain_t *domain)
return 192;
}
void rpl_policy_set_parent_confirmation_request(bool confirmation_requested)
{
rpl_policy_parent_confirmation_req = confirmation_requested;
}
bool rpl_policy_parent_confirmation_requested(void)
{
return rpl_policy_parent_confirmation_req;
}
#ifdef RPL_STRUCTURES_H_
#error "rpl_structures.h should not be included by rpl_policy.c"

View File

@ -54,5 +54,7 @@ uint_fast8_t rpl_policy_mrhof_parent_set_size(const rpl_domain_t *domain);
uint16_t rpl_policy_mrhof_max_link_metric(const rpl_domain_t *domain);
uint16_t rpl_policy_mrhof_parent_switch_threshold(const rpl_domain_t *domain);
uint16_t rpl_policy_mrhof_max_rank_stretch_for_extra_parents(const rpl_domain_t *domain);
bool rpl_policy_parent_confirmation_requested(void);
void rpl_policy_set_parent_confirmation_request(bool confirmation_requested);
#endif /* RPL_POLICY_H_ */

View File

@ -52,6 +52,7 @@ struct rpl_neighbour {
bool was_dodag_parent: 1; // Was a DODAG parent (used only during parent selection)
bool have_global_address: 1; // Global address known
bool considered: 1; // Have considered at least once for parent selection
bool confirmed: 1; // Confirmed
unsigned dodag_pref: 4; // Preference indication for DODAG parents (0=best)
uint8_t dao_path_control; // Path control bit assignments for DAO parent
uint8_t old_dao_path_control;
@ -136,6 +137,7 @@ struct rpl_dao_target {
uint8_t prefix_len;
uint8_t path_sequence;
uint8_t path_control;
uint8_t response_wait_time;
int8_t interface_id;
uint32_t lifetime; /* Seconds */
uint32_t descriptor; /* Target descriptor */
@ -146,6 +148,8 @@ struct rpl_dao_target {
bool descriptor_present: 1; /* Target descriptor specified */
bool need_seq_inc: 1;
bool connected: 1; /* We know this target has a path to the root */
bool trig_confirmation_state: 1; /* Enable confirmation to parent's */
bool active_confirmation_state: 1;
union {
#ifdef HAVE_RPL_ROOT
rpl_dao_root_t root; /* Info specific to a non-storing root */
@ -175,12 +179,14 @@ struct rpl_instance {
bool dio_not_consistent: 1; /* Something changed - not consistent this period */
bool dao_in_transit: 1; /* If we have a DAO in transit */
bool requested_dao_ack: 1; /* If we requested an ACK (so we retry if no ACK, rather than assuming success) */
bool pending_neighbour_confirmation: 1; /* if we have not finished address registration state to parent */
uint8_t poison_count;
uint8_t repair_dis_count;
uint16_t repair_dis_timer;
uint32_t last_dao_trigger_time;
uint16_t srh_error_count; /* SRH errors since last DAO trigger */
NS_LIST_HEAD(rpl_dodag_t, link) dodags; /* List of DODAGs */
rpl_neighbour_t *wait_response;
rpl_neighbour_list_t candidate_neighbours; /* Candidate neighbour set */
// rpl_neighbour_list_t old_neighbours; /* Old neighbours (without a live DODAG version) */
rpl_dodag_version_t *current_dodag_version; /* Pointer to DODAG version we are a member of (if any) */

View File

@ -343,6 +343,8 @@ void rpl_instance_trigger_parent_selection(rpl_instance_t *instance, uint16_t de
static void rpl_instance_parent_selection_timer(rpl_instance_t *instance, uint16_t seconds)
{
if (instance->parent_selection_timer > seconds) {
instance->parent_selection_timer -= seconds;
} else if (instance->parent_selection_timer != 0) {
@ -405,6 +407,7 @@ rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *version, const uint8_
neighbour->g_mop_prf = g_mop_prf;
neighbour->dtsn = dtsn;
neighbour->dao_path_control = 0;
neighbour->confirmed = 0;
/* Need to limit number of neighbours here - chucking worst neighbour */
@ -423,6 +426,11 @@ rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *version, const uint8_
void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour)
{
rpl_dao_target_t *dao_target = rpl_instance_get_active_target_confirmation(instance);
if (dao_target && instance->wait_response == neighbour) {
instance->wait_response = NULL;
}
rpl_downward_neighbour_gone(instance, neighbour);
ns_list_remove(&instance->candidate_neighbours, neighbour);
if (neighbour->dao_path_control) {
@ -1280,7 +1288,7 @@ static void rpl_instance_update_system_dio_route(rpl_instance_t *instance, rpl_n
uint8_t metric = ipv6_route_pref_to_metric(pref) + parent->dodag_pref;
ipv6_route_add_metric(route->prefix, route->prefix_len, parent->interface_id, parent->ll_address, ROUTE_RPL_DIO, parent, instance->id, rpl_aged_lifetime(route->lifetime, parent->dio_timestamp), metric);
ipv6_route_add_metric(route->prefix, route->prefix_len, parent->interface_id, parent->ll_address, ROUTE_RPL_DIO, parent, instance->id, route->lifetime, metric);
}
/* Called when a DIO has been received */
@ -1290,14 +1298,14 @@ void rpl_dodag_update_implicit_system_routes(rpl_dodag_t *dodag, rpl_neighbour_t
return;
}
uint32_t aged_default = rpl_aged_lifetime(rpl_default_lifetime(dodag), parent->dio_timestamp);
uint32_t default_lifetime = rpl_default_lifetime(dodag);
uint8_t metric = IPV6_ROUTE_DEFAULT_METRIC + parent->dodag_pref;
/* Always add the "root" default route - only used for per-instance lookup */
ipv6_route_add_metric(NULL, 0, parent->interface_id, parent->ll_address, ROUTE_RPL_INSTANCE, parent, dodag->instance->id, aged_default, metric);
ipv6_route_add_metric(NULL, 0, parent->interface_id, parent->ll_address, ROUTE_RPL_INSTANCE, parent, dodag->instance->id, default_lifetime, metric);
/* Also add a specific route to the DODAGID */
ipv6_route_add_metric(dodag->id, 128, parent->interface_id, parent->ll_address, ROUTE_RPL_ROOT, parent, dodag->instance->id, aged_default, metric);
ipv6_route_add_metric(dodag->id, 128, parent->interface_id, parent->ll_address, ROUTE_RPL_ROOT, parent, dodag->instance->id, default_lifetime, metric);
}
@ -1365,7 +1373,8 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance)
}
ns_list_foreach_safe(rpl_neighbour_t, n, &instance->candidate_neighbours) {
if (rpl_aged_lifetime(rpl_default_lifetime(n->dodag_version->dodag), n->dio_timestamp) == 0) {
//Remove a Parent candidates which are not heared a long time ago and not slected ones
if (!n->dodag_parent && (rpl_aged_lifetime(rpl_default_lifetime(n->dodag_version->dodag), n->dio_timestamp) == 0)) {
rpl_delete_neighbour(instance, n);
continue;
}
@ -1406,6 +1415,9 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance)
if (original_preferred != preferred_parent) {
protocol_stats_update(STATS_RPL_PARENT_CHANGE, 1);
if (preferred_parent) {
tr_debug("New preferred parent %s", trace_array(preferred_parent->ll_address, 16));
}
}
// Sets new preferred parent
@ -1605,19 +1617,48 @@ uint16_t rpl_instance_current_rank(const rpl_instance_t *instance)
return instance->current_rank;
}
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr)
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr, bool selected)
{
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
if (neighbour->dodag_parent && addr_ipv6_equal(neighbour->ll_address, ipv6_addr)) {
return true;
}
if (!neighbour->dodag_parent) {
if (selected && !neighbour->dodag_parent) {
// list is ordered so first encounter of false means no more parents in list
return false;
}
if (addr_ipv6_equal(neighbour->ll_address, ipv6_addr)) {
if (!selected) {
return true;
}
if (!neighbour->dodag_parent) {
return false;
}
return true;
}
}
return false;
}
uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents)
{
uint16_t parent_list = 0;
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
if (selected_parents) {
if (neighbour->dodag_parent) {
parent_list++;
}
} else {
parent_list++;
}
}
return parent_list;
}
void rpl_instance_neighbor_delete(rpl_instance_t *instance, const uint8_t *ipv6_addr)
{
ns_list_foreach_safe(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
@ -1633,6 +1674,8 @@ void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds)
ns_list_foreach(rpl_dodag_t, dodag, &instance->dodags) {
rpl_dodag_slow_timer(dodag, seconds);
}
rpl_instance_parent_address_reg_timer_update(instance, seconds);
rpl_instance_parent_selection_timer(instance, seconds);
if (!rpl_instance_preferred_parent(instance)) {
protocol_stats_update(STATS_RPL_TIME_NO_NEXT_HOP, 1);
@ -1665,6 +1708,10 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks)
if (rpl_dodag_am_leaf(dodag) && !instance->poison_count) {
return;
}
/* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */
if (instance->dao_in_transit || instance->delay_dao_timer > 0) {
return;
}
if (trickle_timer(&instance->dio_timer, &dodag->dio_timer_params, ticks)) {
instance->dio_not_consistent = false;
rpl_instance_dio_trigger(instance, NULL, NULL);
@ -1845,4 +1892,26 @@ bool rpl_upward_read_dodag_info(const rpl_instance_t *instance, rpl_dodag_info_t
return true;
}
bool rpl_upward_accept_prefix_update(const rpl_dodag_t *dodag_info, const rpl_neighbour_t *neighbour, const rpl_neighbour_t *pref_parent)
{
//Accept allways from Pref parent or before it is selected
if (!pref_parent || neighbour == pref_parent) {
return true;
}
//Accept only same or higher version number
if (rpl_dodag_version_compare(neighbour->dodag_version, pref_parent->dodag_version) & (RPL_CMP_EQUAL | RPL_CMP_GREATER)) {
//Calculate Time between from last dio from parent and this neighbour
//neighbour dio_timestamp >= pref_parent's, because it's a newly-received message
uint32_t time_between_parent = neighbour->dio_timestamp - pref_parent->dio_timestamp;
uint32_t accepted_time = (uint32_t)dodag_info->dio_timer_params.Imax * 2;
//Accept prefix Update If Time from last DIO is more than 2 x Max
if (accepted_time < time_between_parent) {
return true;
}
}
return false;
}
#endif /* HAVE_RPL */

View File

@ -83,7 +83,8 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, struct protocol_interfac
void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair);
bool rpl_instance_local_repair(const rpl_instance_t *instance);
uint16_t rpl_instance_current_rank(const rpl_instance_t *instance);
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr);
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr, bool selected);
uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents);
void rpl_instance_neighbor_delete(rpl_instance_t *instance, const uint8_t *ipv6_addr);
void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds);
@ -139,11 +140,14 @@ void rpl_neighbour_update_dodag_version(rpl_neighbour_t *neighbour, rpl_dodag_ve
bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn);
rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour);
void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag);
void rpl_instance_run_parent_selection(rpl_instance_t *instance);
void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn);
bool rpl_upward_read_dodag_info(const rpl_instance_t *instance, struct rpl_dodag_info_t *dodag_info);
bool rpl_upward_accept_prefix_update(const rpl_dodag_t *dodag_info, const rpl_neighbour_t *neighbour, const rpl_neighbour_t *pref_parent);
uint16_t rpl_upward_read_dao_target_list_size(const rpl_instance_t *instance, const uint8_t *target_prefix);
#endif /* RPL_UPWARD_H_ */

View File

@ -989,6 +989,7 @@ void tls_server_finnish_handle_start(sec_suite_t *tls_suite)
#ifdef PANA_SERVER_API
static buffer_t *tls_verify_handler(uint8_t certi_rx, tls_header_t *tls_header_ptr, buffer_t *buf, sec_suite_t *tls_suite)
{
(void) certi_rx;
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
tls_heap->client_verify_buf_len = tls_header_ptr->length;
if (tls_heap->client_verify_buf) {

View File

@ -33,65 +33,15 @@
#define TRACE_GROUP "kmar"
#define KMP_ADDR_DYN_ALLOC 0x80
#define KMP_ADDR_TYPE_MASK 0x0F
typedef struct {
uint8_t type;
uint8_t eui_64[8];
address_t ip_addr;
uint16_t port;
} kmp_eui_64_ip_addr_t;
kmp_addr_t *kmp_address_create(kmp_addr_e type, const uint8_t *eui_64)
{
uint8_t size;
if (type == KMP_ADDR_EUI_64) {
size = sizeof(kmp_addr_t);
} else if (type == KMP_ADDR_EUI_64_AND_IP) {
size = sizeof(kmp_eui_64_ip_addr_t);
} else {
return 0;
}
kmp_addr_t *addr = ns_dyn_mem_alloc(size);
if (!addr) {
return 0;
}
kmp_address_init(type, addr, eui_64);
addr->type |= KMP_ADDR_DYN_ALLOC;
return addr;
}
void kmp_address_init(kmp_addr_e type, kmp_addr_t *addr, const uint8_t *eui_64)
{
uint8_t size;
if (type == KMP_ADDR_EUI_64) {
size = sizeof(kmp_addr_t);
} else if (type == KMP_ADDR_EUI_64_AND_IP) {
size = sizeof(kmp_eui_64_ip_addr_t);
} else {
return;
}
kmp_addr_t *kmp_addr = addr;
memset(addr, 0, size);
kmp_addr->type = type;
memset(addr, 0, sizeof(kmp_addr_t));
addr->type = type;
if (eui_64) {
memcpy(kmp_addr->eui_64, eui_64, 8);
memcpy(addr->eui_64, eui_64, 8);
}
}
void kmp_address_delete(kmp_addr_t *addr)
{
if (addr && (addr->type & KMP_ADDR_DYN_ALLOC)) {
ns_dyn_mem_free(addr);
}
}
const uint8_t *kmp_address_eui_64_get(const kmp_addr_t *addr)
{
@ -104,20 +54,11 @@ const uint8_t *kmp_address_eui_64_get(const kmp_addr_t *addr)
const uint8_t *kmp_address_ip_get(const kmp_addr_t *addr)
{
if (!addr || (addr->type & KMP_ADDR_TYPE_MASK) != KMP_ADDR_EUI_64_AND_IP) {
if (!addr || addr->type != KMP_ADDR_EUI_64_AND_IP) {
return NULL;
}
return ((kmp_eui_64_ip_addr_t *)addr)->ip_addr;
}
uint16_t kmp_address_port_get(const kmp_addr_t *addr)
{
if (!addr || (addr->type & KMP_ADDR_TYPE_MASK) != KMP_ADDR_EUI_64_AND_IP) {
return 0;
}
return ((kmp_eui_64_ip_addr_t *)addr)->port;
return addr->relay_address;
}
int8_t kmp_address_eui_64_set(kmp_addr_t *addr, const uint8_t *eui64)
@ -130,26 +71,6 @@ int8_t kmp_address_eui_64_set(kmp_addr_t *addr, const uint8_t *eui64)
return 0;
}
int8_t kmp_address_ip_set(kmp_addr_t *addr, const uint8_t *ip_addr)
{
if (!addr || !ip_addr || (addr->type & KMP_ADDR_TYPE_MASK) != KMP_ADDR_EUI_64_AND_IP) {
return -1;
}
memcpy(((kmp_eui_64_ip_addr_t *)addr)->ip_addr, ip_addr, sizeof(address_t));
return 0;
}
int8_t kmp_address_port_set(kmp_addr_t *addr, const uint16_t port)
{
if (!addr || (addr->type & KMP_ADDR_TYPE_MASK) != KMP_ADDR_EUI_64_AND_IP) {
return -1;
}
((kmp_eui_64_ip_addr_t *)addr)->port = port;
return 0;
}
int8_t kmp_address_copy(kmp_addr_t *to_addr, const kmp_addr_t *from_addr)
{
if (!to_addr || !from_addr) {
@ -158,16 +79,13 @@ int8_t kmp_address_copy(kmp_addr_t *to_addr, const kmp_addr_t *from_addr)
memcpy(to_addr->eui_64, from_addr->eui_64, 8);
kmp_eui_64_ip_addr_t *to_ip_addr = (kmp_eui_64_ip_addr_t *) to_addr;
kmp_eui_64_ip_addr_t *from_ip_addr = (kmp_eui_64_ip_addr_t *) from_addr;
if ((to_ip_addr->type & KMP_ADDR_TYPE_MASK) == KMP_ADDR_EUI_64_AND_IP
&& (from_ip_addr->type & KMP_ADDR_TYPE_MASK) == KMP_ADDR_EUI_64_AND_IP) {
memcpy(to_ip_addr->ip_addr, from_ip_addr->ip_addr, sizeof(address_t));
to_ip_addr->port = from_ip_addr->port;
} else if ((to_ip_addr->type & KMP_ADDR_TYPE_MASK) == KMP_ADDR_EUI_64_AND_IP) {
memset(to_ip_addr->ip_addr, 0, sizeof(address_t));
to_ip_addr->port = 0;
if (to_addr->type == KMP_ADDR_EUI_64_AND_IP
&& from_addr->type == KMP_ADDR_EUI_64_AND_IP) {
memcpy(to_addr->relay_address, from_addr->relay_address, sizeof(address_t));
to_addr->port = from_addr->port;
} else if (to_addr->type == KMP_ADDR_EUI_64_AND_IP) {
memset(to_addr->relay_address, 0, sizeof(address_t));
to_addr->port = 0;
}
return 0;

View File

@ -26,19 +26,10 @@ typedef enum {
typedef struct {
uint8_t type;
uint8_t eui_64[8];
address_t relay_address;
uint16_t port;
} kmp_addr_t;
/**
* kmp_address_create creates address
*
* \param type address type
* \param eui_64 EUI-64
*
* \return address
*
*/
kmp_addr_t *kmp_address_create(kmp_addr_e type, const uint8_t *eui_64);
/**
* kmp_address_init initializes address
*
@ -49,13 +40,6 @@ kmp_addr_t *kmp_address_create(kmp_addr_e type, const uint8_t *eui_64);
*/
void kmp_address_init(kmp_addr_e type, kmp_addr_t *addr, const uint8_t *eui_64);
/**
* kmp_address_delete deletes address
*
* \param addr address
*
*/
void kmp_address_delete(kmp_addr_t *addr);
/**
* kmp_address_eui_64_get get EUI-64
@ -77,15 +61,6 @@ const uint8_t *kmp_address_eui_64_get(const kmp_addr_t *addr);
*/
const uint8_t *kmp_address_ip_get(const kmp_addr_t *addr);
/**
* kmp_address_port_get get port
*
* \param addr address
*
* \return port
*
*/
uint16_t kmp_address_port_get(const kmp_addr_t *addr);
/**
* kmp_address_eui_64_set set EUI-64
@ -99,30 +74,6 @@ uint16_t kmp_address_port_get(const kmp_addr_t *addr);
*/
int8_t kmp_address_eui_64_set(kmp_addr_t *addr, const uint8_t *eui64);
/**
* kmp_address_ip_set set IP address
*
* \param addr address
* \param ip_addr IP address
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t kmp_address_ip_set(kmp_addr_t *addr, const uint8_t *ip_addr);
/**
* kmp_address_port_set set port address
*
* \param addr address
* \param port port
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t kmp_address_port_set(kmp_addr_t *addr, const uint16_t port);
/**
* kmp_address_copy copies address
*

View File

@ -251,10 +251,10 @@ static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64,
kmp->service->addr_get(kmp->service, kmp, &local_addr, &remote_addr);
if (local_eui64) {
memcpy(local_eui64, kmp_address_eui_64_get(&local_addr), 8);
memcpy(local_eui64, local_addr.eui_64, 8);
}
if (remote_eui64) {
memcpy(remote_eui64, kmp_address_eui_64_get(&remote_addr), 8);
memcpy(remote_eui64, remote_addr.eui_64, 8);
}
}

View File

@ -129,9 +129,9 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, cons
//Build UPD Relay
uint8_t *ptr = pdu;
memcpy(ptr, kmp_address_ip_get(addr), 16);
memcpy(ptr, addr->relay_address, 16);
ptr += 16;
ptr = common_write_16_bit(kmp_address_port_get(addr), ptr);
ptr = common_write_16_bit(addr->port, ptr);
memcpy(ptr, kmp_address_eui_64_get(addr), 8);
ptr += 8;
*ptr = kmp_id;
@ -169,14 +169,15 @@ static void kmp_socket_if_socket_cb(void *ptr)
ns_dyn_mem_free(pdu);
return;
}
uint8_t *relay_address, *euid64;
uint16_t relay_port;
kmp_addr_t addr;
addr.type = KMP_ADDR_EUI_64_AND_IP;
uint8_t *data_ptr = pdu;
relay_address = data_ptr;
memcpy(addr.relay_address, data_ptr, 16);
data_ptr += 16;
relay_port = common_read_16_bit(data_ptr);
addr.port = common_read_16_bit(data_ptr);
data_ptr += 2;
euid64 = data_ptr;
memcpy(addr.eui_64, data_ptr, 8);
data_ptr += 8;
kmp_type_e type = kmp_api_type_from_id_get(*data_ptr++);
@ -185,17 +186,8 @@ static void kmp_socket_if_socket_cb(void *ptr)
return;
}
kmp_addr_t *addr = kmp_address_create(KMP_ADDR_EUI_64_AND_IP, euid64);
if (!addr) {
ns_dyn_mem_free(pdu);
return;
}
kmp_address_ip_set(addr, relay_address);
kmp_address_port_set(addr, relay_port);
kmp_service_msg_if_receive(socket_if->kmp_service, type, addr, data_ptr, cb_data->d_len - 27);
kmp_address_delete(addr);
kmp_service_msg_if_receive(socket_if->kmp_service, type, &addr, data_ptr, cb_data->d_len - 27);
ns_dyn_mem_free(pdu);
}

View File

@ -272,7 +272,7 @@ int8_t sec_prot_lib_pmkid_calc(const uint8_t *pmk, const uint8_t *auth_eui64, co
const uint8_t pmk_string_val[] = {"PMK Name"};
const uint8_t pmk_string_val_len = sizeof(pmk_string_val) - 1;
const uint8_t data_len = pmk_string_val_len + EUI64_LEN + EUI64_LEN;
uint8_t data_len = pmk_string_val_len + EUI64_LEN + EUI64_LEN;
uint8_t data[data_len];
uint8_t *ptr = data;
memcpy(ptr, pmk_string_val, pmk_string_val_len);
@ -294,7 +294,7 @@ int8_t sec_prot_lib_ptkid_calc(const uint8_t *ptk, const uint8_t *auth_eui64, co
const uint8_t ptk_string_val[] = {"PTK Name"};
const uint8_t ptk_string_val_len = sizeof(ptk_string_val) - 1;
const uint8_t data_len = ptk_string_val_len + EUI64_LEN + EUI64_LEN;
uint8_t data_len = ptk_string_val_len + EUI64_LEN + EUI64_LEN;
uint8_t data[data_len];
uint8_t *ptr = data;
memcpy(ptr, ptk_string_val, ptk_string_val_len);

View File

@ -97,6 +97,11 @@ static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int l
#endif
#ifdef MBEDTLS_PLATFORM_MEMORY
// Disable for now
//#define TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
#endif
#ifdef TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
static void *tls_sec_prot_lib_mem_calloc(size_t count, size_t size);
static void tls_sec_prot_lib_mem_free(void *ptr);
#endif
@ -105,9 +110,8 @@ int8_t tls_sec_prot_lib_init(tls_security_t *sec)
{
const char *pers = "ws_tls";
#ifdef MBEDTLS_PLATFORM_MEMORY
// Disable for now
//mbedtls_platform_set_calloc_free(tls_sec_prot_lib_mem_calloc, tls_sec_prot_lib_mem_free);
#ifdef TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
mbedtls_platform_set_calloc_free(tls_sec_prot_lib_mem_calloc, tls_sec_prot_lib_mem_free);
#endif
@ -497,7 +501,7 @@ static int tls_sec_lib_entropy_poll(void *ctx, unsigned char *output, size_t len
return (0);
}
#ifdef MBEDTLS_PLATFORM_MEMORY
#ifdef TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
static void *tls_sec_prot_lib_mem_calloc(size_t count, size_t size)
{
void *mem_ptr = ns_dyn_mem_temporary_alloc(count * size);

View File

@ -100,7 +100,6 @@ bool blacklist_reject(const uint8_t *ll64_address)
tr_debug("blacklist full reject");
return true;
} else {
tr_debug("blacklist not found %s", trace_array(ll64_address + 8, 8));
return false;
}
}
@ -144,7 +143,6 @@ void blacklist_update(const uint8_t *ll64_address, bool success)
}
/* TTL is blacklist entry lifetime + from 1.0 to 1.5 * interval */
blacklist_entry->ttl = blacklist_data->blacklist_entry_lifetime + randLIB_randomise_base(blacklist_entry->interval, 0x8000, 0xC000);
tr_debug("Blacklist updated, ttl=%"PRIu16, blacklist_entry->ttl);
} else {
tr_debug("Blacklist add");
blacklist_entry_add(ll64_address + 8);

View File

@ -157,7 +157,7 @@ static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *en
}
}
tr_debug("ETX update possible %u attempts, %u rx ack", storage->attempts_count, storage->received_acks);
//tr_debug("ETX update possible %u attempts, %u rx ack", storage->attempts_count, storage->received_acks);
return true;
@ -318,9 +318,6 @@ uint16_t etx_read(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr
}
attribute_index = mac_neighbor->index;
//tr_debug("Etx Read from atribute %u", attribute_index);
etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index);
if (!entry) {
@ -330,8 +327,6 @@ uint16_t etx_read(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr
uint16_t etx = etx_current_calc(entry->etx, entry->accumulated_failures);
etx >>= 4;
//tr_debug("Etx value %u", etx);
return etx;
}
@ -632,7 +627,6 @@ void etx_max_update_set(uint16_t etx_max_update)
etx_storage_t *etx_storage_entry_get(int8_t interface_id, uint8_t attribute_index)
{
if (etx_info.interface_id != interface_id || !etx_info.etx_storage_list || attribute_index >= etx_info.ext_storage_list_size) {
tr_debug("Unknow ID or un initilized ETX %u", attribute_index);
return NULL;
}
@ -745,7 +739,7 @@ static void etx_accum_failures_callback_needed_check(etx_storage_t *entry, uint8
void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index)
{
tr_debug("Remove attribute %u", attribute_index);
//tr_debug("Remove attribute %u", attribute_index);
uint16_t stored_diff_etx;
etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index);
if (entry && etx_info.callback_ptr) {
@ -780,7 +774,7 @@ void etx_neighbor_remove(int8_t interface_id, uint8_t attribute_index)
void etx_neighbor_add(int8_t interface_id, uint8_t attribute_index)
{
tr_debug("Add attribute %u", attribute_index);
//tr_debug("Add attribute %u", attribute_index);
uint16_t stored_diff_etx;
etx_storage_t *entry = etx_storage_entry_get(interface_id, attribute_index);
if (entry && etx_info.callback_ptr) {
@ -804,12 +798,7 @@ void etx_cache_timer(int8_t interface_id, uint16_t seconds_update)
}
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return;
}
if (!mac_neighbor_info(interface)) {
if (!interface || !mac_neighbor_info(interface)) {
return;
}

View File

@ -71,7 +71,7 @@ fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
fhss_struct->bs->fhss_configuration = *fhss_configuration;
fhss_struct->bs->fhss_stats_ptr = fhss_statistics;
fhss_struct->fhss_stats_ptr = fhss_statistics;
fhss_struct->number_of_channels = channel_count;
// set a invalid id to tasklet_id, so we know that one is not started yet

View File

@ -97,7 +97,6 @@ struct fhss_bs {
uint16_t channel_list_counter;
uint16_t synch_panid;
uint32_t synch_interval;
struct fhss_statistics *fhss_stats_ptr;
struct fhss_beacon_info *fhss_beacon_info_store;
struct fhss_configuration fhss_configuration;
struct fhss_synch_configuration synch_configuration;

View File

@ -48,6 +48,7 @@ struct fhss_structure {
struct fhss_ws *ws;
struct fhss_timer platform_functions;
struct fhss_callback callbacks;
struct fhss_statistics *fhss_stats_ptr;
fhss_failed_tx_list_t fhss_failed_tx_list;
uint8_t synch_parent[8];
};

View File

@ -24,6 +24,7 @@
#include "Service_Libs/fhss/fhss.h"
#include "Service_Libs/fhss/fhss_common.h"
#include "Service_Libs/fhss/fhss_ws.h"
#include "Service_Libs/fhss/fhss_statistics.h"
#include "ns_trace.h"
#define TRACE_GROUP "fhss"
@ -138,3 +139,12 @@ int ns_fhss_ws_set_hop_count(const fhss_api_t *fhss_api, const uint8_t hop_count
}
return fhss_ws_set_hop_count(fhss_structure, hop_count);
}
int ns_fhss_statistics_start(const fhss_api_t *fhss_api, fhss_statistics_t *fhss_statistics)
{
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
if (!fhss_structure) {
return -1;
}
return fhss_statistics_start(fhss_structure, fhss_statistics);
}

View File

@ -24,23 +24,35 @@
void fhss_stats_update(fhss_structure_t *fhss_structure, fhss_stats_type_t type, uint32_t update_val)
{
if (fhss_structure->bs->fhss_stats_ptr) {
if (fhss_structure->fhss_stats_ptr) {
switch (type) {
case STATS_FHSS_DRIFT_COMP:
fhss_structure->bs->fhss_stats_ptr->fhss_drift_compensation = update_val;
fhss_structure->fhss_stats_ptr->fhss_drift_compensation = update_val;
break;
case STATS_FHSS_HOP_COUNT:
fhss_structure->bs->fhss_stats_ptr->fhss_hop_count = update_val;
fhss_structure->fhss_stats_ptr->fhss_hop_count = update_val;
break;
case STATS_FHSS_SYNCH_INTERVAL:
fhss_structure->bs->fhss_stats_ptr->fhss_synch_interval = update_val;
fhss_structure->fhss_stats_ptr->fhss_synch_interval = update_val;
break;
case STATS_FHSS_AVG_SYNCH_FIX:
fhss_structure->bs->fhss_stats_ptr->fhss_prev_avg_synch_fix = update_val;
fhss_structure->fhss_stats_ptr->fhss_prev_avg_synch_fix = update_val;
break;
case STATS_FHSS_SYNCH_LOST:
fhss_structure->bs->fhss_stats_ptr->fhss_synch_lost += update_val;
fhss_structure->fhss_stats_ptr->fhss_synch_lost += update_val;
break;
case STATS_FHSS_UNKNOWN_NEIGHBOR:
fhss_structure->fhss_stats_ptr->fhss_unknown_neighbor += update_val;
break;
case STATS_FHSS_CHANNEL_RETRY:
fhss_structure->fhss_stats_ptr->fhss_channel_retry += update_val;
break;
}
}
}
int fhss_statistics_start(fhss_structure_t *fhss_structure, fhss_statistics_t *fhss_statistics)
{
fhss_structure->fhss_stats_ptr = fhss_statistics;
return 0;
}

View File

@ -23,8 +23,11 @@ typedef enum {
STATS_FHSS_SYNCH_INTERVAL,
STATS_FHSS_AVG_SYNCH_FIX,
STATS_FHSS_SYNCH_LOST,
STATS_FHSS_UNKNOWN_NEIGHBOR,
STATS_FHSS_CHANNEL_RETRY
} fhss_stats_type_t;
void fhss_stats_update(fhss_structure_t *fhss_structure, fhss_stats_type_t type, uint32_t update_val);
int fhss_statistics_start(fhss_structure_t *fhss_structure, fhss_statistics_t *fhss_statistics);
#endif /* FHSS_STATISTICS_H_ */

View File

@ -20,6 +20,7 @@
#include "fhss_config.h"
#include "fhss.h"
#include "fhss_common.h"
#include "fhss_statistics.h"
#include "channel_list.h"
#include "channel_functions.h"
#include "fhss_ws.h"
@ -143,7 +144,7 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
fhss_struct->ws->fhss_configuration = *fhss_configuration;
fhss_struct->number_of_channels = channel_count;
fhss_struct->own_hop = 0xff;
fhss_ws_set_hop_count(fhss_struct, 0xff);
fhss_struct->rx_channel = fhss_configuration->unicast_fixed_channel;
fhss_struct->ws->min_synch_interval = DEFAULT_MIN_SYNCH_INTERVAL;
fhss_set_txrx_slot_length(fhss_struct);
@ -472,6 +473,7 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a
if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED) {
fhss_ws_neighbor_timing_info_t *neighbor_timing_info = fhss_structure->ws->get_neighbor_info(api, destination_address);
if (!neighbor_timing_info) {
fhss_stats_update(fhss_structure, STATS_FHSS_UNKNOWN_NEIGHBOR, 1);
return -2;
}
// TODO: WS bootstrap has to store neighbors number of channels
@ -687,6 +689,7 @@ static bool fhss_ws_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle,
// Create new failure handle and return true to retransmit
fhss_failed_handle_add(fhss_structure, handle, fhss_structure->rx_channel);
}
fhss_stats_update(fhss_structure, STATS_FHSS_CHANNEL_RETRY, 1);
return true;
}
@ -858,9 +861,11 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
drift_per_ms_tmp = -MAX_DRIFT_COMPENSATION_STEP;
}
fhss_structure->ws->drift_per_millisecond_ns += drift_per_ms_tmp;
fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, NS_TO_US(fhss_structure->ws->drift_per_millisecond_ns * bc_timing_info->broadcast_dwell_interval));
}
tr_debug("synch to parent: %s, drift: %"PRIi32"ms in %"PRIu32" seconds, compensation: %"PRIi32"ns per ms", trace_array(eui64, 8), true_bc_interval_offset - own_bc_interval_offset + ((int32_t)(fhss_structure->ws->bc_slot - own_bc_slot) * bc_timing_info->broadcast_interval), US_TO_S(time_since_last_synch_us), fhss_structure->ws->drift_per_millisecond_ns);
}
fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, US_TO_S(time_since_last_synch_us));
return 0;
}
@ -915,6 +920,8 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count)
{
fhss_structure->own_hop = hop_count;
fhss_stats_update(fhss_structure, STATS_FHSS_HOP_COUNT, fhss_structure->own_hop);
return 0;
}
#endif // HAVE_WS

View File

@ -26,8 +26,6 @@
#include "Core/include/ns_address_internal.h"
#include "platform/topo_trace.h"
#define TRACE_GROUP "mnei"
mac_neighbor_table_t *mac_neighbor_table_create(uint8_t table_size, neighbor_entry_remove_notify *remove_cb, neighbor_entry_nud_notify *nud_cb, void *user_indentifier)
{
mac_neighbor_table_t *table_class = ns_dyn_mem_alloc(sizeof(mac_neighbor_table_t) + sizeof(mac_neighbor_table_entry_t) * table_size);
@ -111,11 +109,9 @@ void mac_neighbor_table_neighbor_timeout_update(mac_neighbor_table_t *table_clas
if (table_class->user_nud_notify_cb(cur, table_class->table_user_identifier)) {
table_class->active_nud_process++;
cur->nud_active = true;
tr_debug("Nud started index %u : %"PRIu32" time ", cur->index, cur->lifetime);
}
} else {
tr_debug("Node index %u time out ", cur->index);
neighbor_table_class_remove_entry(table_class, cur);
}
}
@ -176,7 +172,6 @@ void mac_neighbor_table_neighbor_refresh(mac_neighbor_table_t *table_class, mac_
neighbor_entry->lifetime = life_time;
neighbor_entry->link_lifetime = life_time;
if (neighbor_entry->nud_active) {
tr_debug("Node index NUD response %u : %"PRIu32" time ", neighbor_entry->index, neighbor_entry->lifetime);
neighbor_entry->nud_active = false;
table_class->active_nud_process--;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2017-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "Core/include/ns_monitor.h"
#include "mac_api.h" // for mcps_packet_ingress_rate_limit_by_memory
#include "MAC/IEEE802_15_4/mac_mcps_sap.h" // for mcps_packet_ingress_rate_limit_by_memory
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);
}
int ns_conf_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage)
{
return mcps_packet_ingress_rate_limit_by_memory(free_heap_percentage);
}

View File

@ -303,9 +303,15 @@ ipv6_neighbour_t *ipv6_neighbour_lookup_or_create(ipv6_neighbour_cache_t *cache,
{
uint_fast16_t count = 0;
ipv6_neighbour_t *entry = NULL;
ipv6_neighbour_t *garbage_possible_entry = NULL;
ns_list_foreach(ipv6_neighbour_t, cur, &cache->list) {
count++;
if (cur->type == IP_NEIGHBOUR_GARBAGE_COLLECTIBLE) {
garbage_possible_entry = cur;
count++;
}
if (addr_ipv6_equal(cur->ip_address, address)) {
if (cur != ns_list_get_first(&cache->list)) {
ns_list_remove(&cache->list, cur);
@ -315,9 +321,9 @@ ipv6_neighbour_t *ipv6_neighbour_lookup_or_create(ipv6_neighbour_cache_t *cache,
}
}
if (count >= neighbour_cache_config.max_entries) {
entry = ns_list_get_last(&cache->list);
ipv6_neighbour_entry_remove(cache, entry);
if (count >= neighbour_cache_config.max_entries && garbage_possible_entry) {
//Remove Last storaged IP_NEIGHBOUR_GARBAGE_COLLECTIBLE type entry
ipv6_neighbour_entry_remove(cache, garbage_possible_entry);
}
// Allocate new - note we have a basic size, plus enough for the LL address,
@ -1066,6 +1072,23 @@ void ipv6_destination_redirect(const uint8_t *dest_addr, const uint8_t *sender_a
}
#endif
void ipv6_destination_cache_forced_gc(bool full_gc)
{
int gc_count = ns_list_count(&ipv6_destination_cache);
/* Minimize size of destination cache:
* - keep absolutely minimum number of entries if not full gc
* - clear all entries in case of full gc
**/
ns_list_foreach_reverse_safe(ipv6_destination_t, entry, &ipv6_destination_cache) {
if (entry->lifetime == 0 || gc_count > destination_cache_config.long_term_entries || full_gc) {
ns_list_remove(&ipv6_destination_cache, entry);
ipv6_destination_release(entry);
gc_count--;
}
}
}
static void ipv6_destination_release(ipv6_destination_t *dest)
{
if (--dest->refcount == 0) {

View File

@ -73,7 +73,7 @@ typedef enum ipv6_route_src {
ROUTE_RPL_DAO, /* Explicitly advertised in DAO, Storing mode */
ROUTE_RPL_DAO_SR, /* Explicitly advertised in DAO, Root Source Routes in Non-Storing mode */
ROUTE_RPL_SRH, /* Not in routing table - used in buffers to represent on-link inferred from SRH */
ROUTE_RPL_ROOT, /* Implicit route to DODAG route */
ROUTE_RPL_ROOT, /* Implicit route to DODAG root */
ROUTE_RPL_INSTANCE, /* Implicit instance-specific default upward route (not for general search) */
ROUTE_RPL_FWD_ERROR, /* Not in routing table - used in buffers to represent Forwarding-Error bounce */
ROUTE_MULTICAST, /* Not in routing table - used to represent multicast interface selection */
@ -222,6 +222,7 @@ void ipv6_destination_cache_timer(uint8_t ticks);
#ifdef HAVE_IPV6_ND
void ipv6_destination_redirect(const uint8_t *dest_addr, const uint8_t *sender_addr, const uint8_t *redirect_addr, int8_t interface_id, addrtype_t ll_type, const uint8_t *ll_address);
#endif
void ipv6_destination_cache_forced_gc(bool full_gc);
/* Combined Routing Table (RFC 4191) and Prefix List (RFC 4861) */
/* On-link prefixes have the on_link flag set and next_hop is unset */

View File

@ -828,6 +828,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
}
if (retval != 0) {
tr_warn("dhcp service socket_sendto fails: %i", retval);
} else {
tr_warn("dhcp service socket_sendto %s", trace_ipv6(msg_tr_ptr->addr.address));
}
}
bool dhcp_service_timer_tick(uint16_t ticks)

View File

@ -208,7 +208,7 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_transactionId(ui
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_prefix(int8_t interfaceId, uint8_t *prefix)
{
ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) {
if ((cur->interfaceId == interfaceId)) {
if (cur->interfaceId == interfaceId) {
if (memcmp(cur->iaNontemporalAddress.addressPrefix, prefix, 8) == 0) {
return cur;
}

View File

@ -39,6 +39,7 @@ SRCS += \
source/6LoWPAN/ws/ws_eapol_auth_relay.c \
source/6LoWPAN/ws/ws_eapol_relay_lib.c \
source/6LoWPAN/ws/ws_eapol_pdu.c \
source/6LoWPAN/ws/ws_stats.c \
source/BorderRouter/border_router.c \
source/Common_Protocols/icmpv6.c \
source/Common_Protocols/icmpv6_prefix.c \
@ -51,6 +52,7 @@ SRCS += \
source/Common_Protocols/tcp.c \
source/Common_Protocols/udp.c \
source/Core/ns_address_internal.c \
source/Core/ns_monitor.c \
source/Core/buffer_dyn.c \
source/Core/sockbuf.c \
source/Core/ns_socket.c \
@ -195,6 +197,7 @@ SRCS += \
source/Service_Libs/utils/ns_crc.c \
source/Service_Libs/utils/isqrt.c \
source/Service_Libs/utils/ns_file_system.c \
source/Service_Libs/utils/ns_conf.c \
source/Service_Libs/mdns/ns_mdns_api.c \
source/Service_Libs/mdns/ns_fnet_port.c \
source/Service_Libs/mdns/ns_fnet_events.c \