Squashed 'features/nanostack/sal-stack-nanostack/' changes from 0345477..3c7d50e

3c7d50e Remove test files
d5f5bee Merge branch 'release_internal' into release_external
72b065b Merge pull request #2133 from ARMmbed/few_updates
1da0b9f Fix unittest cleanup
d173249 Adjust GC cleanup threshold and traces
26166d1 Remove ns_sw_mac_packet_ingress_rate_limit_by_mem (#2132)
5305754 Merge pull request #2130 from ARMmbed/IOTTHD-3419
038bc2e Copy ingress rate limiting API to ns_conf
940b516 Fix compiler warnings
64e6ff3 Review corrections
01e7d84 Update GC thresholds, init and traces
1acd1cc Add unit tests for monitor
64c969e Nanostack heap garbage collection
d3330b2 Fix errors found by Coverity (#2131)
da5d2c7 MAC, RPL and ETX trace clean.
eaf8907 Limit amount of incoming packet based on memory (#2128)
0c2b383 Fixed unitest header size compare value for support brodacst shedule.
6c70262 Wi-sun LLC update
7c57343 WS PAN Config handler update
161421b Wi-sun PAN_VERSION lifetime and timeout update
43083ed Fixed broken wi-sun neigbour black list filtering.
0992ee2 Update Pan information data from all selected parent.
cafc142 Fixed Pan advertisment route cost comapre for consistent and incosistent
db81d02 SW MAC timestamp read update
eddf91b Wi-sun neighbor generate limitation
4d6abb3 Added 15 second guarantee time for packet handler before remove link.
9ed97eb SW MAC new API for read current timestamp
6a44829 Stop advertisment RPL prefix if we not have a address and it is not 'A-flag'
d37ce6a Revert "Wi-sun dublicate MPX ID filter support"
d80ebf8 Fix debug trace format.
b1ef0f6 Removed Address reg pending and rady mask from address.
ce672ba Added trace for debugging DHCPv6 failure reason.
aaf2b39 Wi-sun dublicate MPX ID filter support
bd51f9f Merge pull request #2117 from ARMmbed/IOTTHD-3587
b016d52 Fixed DHCPv6 client delete when address was removed to new network discovery.
69fb24b Wi-sun address registration and RPL update
92d3a92 RPL: trace new preferred parent
9a6e4e0 disable multicast NS for wisun
6e13d81 Merge pull request #2113 from ARMmbed/IOTTHD-3577
85aaae7 Refactored the Wi-SUN BBR logic according to design
61f6f5b WS: Added ws stats empty functions
ac191c3 Removed link local address verifycation and dead code.
77076d1 Negative ARO timeout use same timeout than not trusted device.
c4e8735 Wi-sun DHCP solicit max to 15min from 60min.
66615e6 Updated wi-sun BBR min hop rank increase to 196.
9ce41f1 Pendig address registration will move DAO send.
f54ea6b Merge pull request #2110 from ARMmbed/IOTTHD-3577
18dbac2 WS: Implemented ws statistics
3ce95fa FHSS WS: Fixed drift compensation stats
b878bd9 KMP address update
7f18afe PAE controller and NVM update
f692eb8 Wi-SUN border router configure update
386e5ff Wi-sun Update
05b1fe8 do not send periodic DIO messages if DAO registration is not done
6acee47 modified RSL calculation and value in messaging
ee7f218 Modify discovery start timing
1ba806d Wi-SUN NUD send fix
31fb8cd Moved counter config to config.h
cf18063 Added storing of MAC frame counter to NVM
68adb36 Neighbor cache update
8cdd961 Added possibility for Update DHCPv6 client server address.
2dfa536 Merge pull request #2099 from ARMmbed/IOTTHD-3231
8dc200b FHSS: Created statistics for WS
5e67f7c RPL update
bbae493 wi-sun RPL param update
e8567d7 MAC neighbour remove and add trace simplify.
8bb4ab5 Cleaned unnessary debug trace.
3608153 DIO prefix handler update
332735b Disabled Version number periodic update if Dodag max rank inrease is not 0.
940de0b Wi-SUN setup update:
c1a89e5 Merge pull request #2095 from ARMmbed/IOTTHD-3474
f6d81b5 Review corrections
7487ca1 Fix clang-6.0 build error and warnings
cce3fc7 Security protocols are no longer started second time on authenticator

git-subtree-dir: features/nanostack/sal-stack-nanostack
git-subtree-split: 3c7d50e9bd8f100eccf23066d0f0adba4cf9b980
pull/11156/head^2
Arto Kinnunen 2019-08-02 13:52:37 +03:00
parent 1c29564f65
commit c51a57a033
88 changed files with 2022 additions and 768 deletions

View File

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

View File

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

View File

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

62
nanostack/ns_conf.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,7 +33,7 @@ typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t;
typedef struct {
kmp_list_t kmp_list; /**< Ongoing KMP negotiations */
kmp_addr_t *addr; /**< EUI-64 (Relay IP address, Relay port) */
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
sec_prot_keys_t sec_keys; /**< Security keys */
uint32_t ticks; /**< Ticks */
uint16_t retry_ticks; /**< Retry ticks */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

174
source/Core/ns_monitor.c Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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