mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #11156 from artokin/nanostack_patch_for_mbed_os_5_13_x
Nanostack patch release for Mbed OS 5.13.xpull/11104/head
commit
13ee14c624
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ $(TESTDIRS):
|
|||
|
||||
$(CLEANTESTDIRS):
|
||||
@make -C $(@:clean-%=%) clean
|
||||
@rm -fr results
|
||||
|
||||
.PHONY: release
|
||||
release:
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_ */
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in New Issue