mirror of https://github.com/ARMmbed/mbed-os.git
Squashed 'features/nanostack/sal-stack-nanostack/' changes from 3c7d50e..4a19dc4
4a19dc4 Import new thread files f6a021d Removed test files b9e842a Merge branch 'release_internal' into release_external 7d5d869 Merge pull request #2167 from ARMmbed/release_internal_merge 26e2d43 Merge branch 'master' into release_internal f43620f Add support for India band (#2166) 122f158 Merge pull request #2165 from ARMmbed/release_internal_merge 0e65ee5 Added disabling of NA for Thread BR PPP backbone 4c50e52 Added disabling of NA for Wi-SUN BR PPP backbone d2ea325 Moved DAD enabled check to Ipv6 SLAAC handler 49994fc Added PPP interface to nanostack 3383e91 Merge pull request #2163 from ARMmbed/IOTTHD-3558 81f7511 MAC: print RF configs 397240a MAC: Implemented CCA threshold and TX power setting 5907042 Added check for allocation failures in EAPOL 9ed97c9 ETX update: b489415 Add own certificate handling APIS (#2149) 888a0fb fhss_ws: check if 0 used as divider 586f2f2 Merge pull request #2160 from hugueskamba/hk-iotcore-1299-remove-fp-usage-ns_monitor f1d03b1 Remove floating-point usage in Nanostack heap monitor ef88f64 Removed rank comprae and also probe 5 best on the list. a2887d6 Clean PAN id compare trace print. f37dcf2 Wi-SUN NS NUD & Probe send update f7133f8 Merge pull request #2158 from ARMmbed/remove_temp_debug_traces 2dc1a8e fhss_ws: removed temporary debug traces 96f962a Reduce wi-sun NS Probe 0a1beb2 GTK update trigger fix a1d172e Limit Pan config sol timeout after 5 solication. 9d7414b Limit PAE supplikant GTK re-use for authentication from 2->1. 662df08 Fixed Key request address set issue if GTK mismatch is detected. a56b908 Merge pull request #2153 from ARMmbed/IOTTHD-3650 9b33e98 Fixed mac_pd_sap CCA_PREPARE active ACK handler. 035af9a Enhanced ACK GEN and TX update b1beb5d fhss_ws: typecast drift to int32_t f786fc9 Merge pull request #2152 from ARMmbed/fhss_coverity_fix 6efff35 fhss_ws: Coverity fixes d743e91 WS LLC brodacst shedule fix 6a6fb0c Removed old configuration options from Border router API a051865 Merge pull request #2135 from ARMmbed/IOTTHD-3232 ff771b1 Added empty interface function for network name set e94da3c Merge pull request #2146 from ARMmbed/IOTTHD-3571_2 234e649 added network name change function to public API 1770465 fhss_ws: Added temporary debug traces (IOTTHD-3571) d400859 Fix Thread 1.1 unitests (#2145) 38978f3 wi-sun ETX update: 4a71b04 Adjust Thread functions defined for Thread 1.2 (#2139) 4d8dc0d remove border router from pan size calculation fb3363e Merge pull request #2141 from ARMmbed/IOTTHD-3571 f01c5f2 fhss_ws: conversion macros/functions to support int64 a7b0027 Suprress dio sending whenRPL is not yet ready f8c9d54 Adjust tracing (#2138) 678eaf8 Moved Thread 1.2 code to to correct place f39d07e Merge pull request #2136 from ARMmbed/IOTTHD-3571 ab23116 FHSS: temporary debug traces (IOTTHD-3571) 09d4b06 MAC: Implemented PHY statistics git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: 4a19dc4784d05a49981a8dce27bed6771e65feb5pull/11335/head
parent
c51a57a033
commit
b7910939da
|
@ -123,6 +123,22 @@ typedef int8_t eth_mac_mac48_address_set(const eth_mac_api_t *api, const uint8_t
|
|||
*/
|
||||
typedef int8_t eth_mac_mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf);
|
||||
|
||||
/**
|
||||
* @brief Set 64 bit interface identifier from IID64
|
||||
* @param api API to handle the request
|
||||
* @param iid64 Pointer having iid64 to be set
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
typedef int8_t eth_mac_iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64);
|
||||
|
||||
/**
|
||||
* @brief Read 64 bit interface identifier
|
||||
* @param api API to handle the request
|
||||
* @param iid64_buf Pointer where IID64 can be written
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
typedef int8_t eth_mac_iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf);
|
||||
|
||||
/**
|
||||
* @brief Upper layer will call this function, when MAC is taken into use
|
||||
* @param api API to initialize
|
||||
|
@ -147,6 +163,9 @@ struct eth_mac_api_s {
|
|||
eth_mac_mac48_address_set *mac48_set; /**< Setter for MAC address */
|
||||
eth_mac_mac48_address_get *mac48_get; /**< Getter for MAC address */
|
||||
|
||||
eth_mac_iid64_address_set *iid64_set; /**< Setter for IID64 */
|
||||
eth_mac_iid64_address_get *iid64_get; /**< Getter for IID64 */
|
||||
|
||||
uint8_t parent_id; /**< Upper layer ID */
|
||||
bool address_resolution_needed; /**< Normal ethernet should set this true for tunnel or false for slip */
|
||||
};
|
||||
|
|
|
@ -264,6 +264,8 @@ typedef enum {
|
|||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||
//NON standard extension
|
||||
macTXPower = 0xf8, /*<TX output power*/
|
||||
macCCAThreshold = 0xf9, /*<CCA threshold*/
|
||||
macMultiCSMAParameters = 0xfa, /*<Multi CSMA parameters*/
|
||||
macRfConfiguration = 0xfb, /*<RF channel configuration parameters*/
|
||||
macAcceptByPassUnknowDevice = 0xfc, /*< Accept data trough MAC if packet is data can be authenticated by group key nad MIC. Security enforsment point must be handled carefully these packets */
|
||||
|
|
|
@ -238,7 +238,9 @@ typedef struct {
|
|||
/** Certificate structure. */
|
||||
typedef struct {
|
||||
const uint8_t *cert; /**< Certificate pointer. */
|
||||
const uint8_t *key; /**< Key pointer. */
|
||||
uint16_t cert_len; /**< Certificate length. */
|
||||
uint16_t key_len; /**< Key length. */
|
||||
} arm_certificate_entry_s;
|
||||
|
||||
/** Certificate Revocation List structure. */
|
||||
|
@ -318,6 +320,20 @@ extern int8_t arm_nwk_interface_ethernet_init(struct eth_mac_api_s *api, const c
|
|||
*/
|
||||
extern int8_t arm_nwk_interface_lowpan_init(struct mac_api_s *api, char *interface_name_ptr);
|
||||
|
||||
/**
|
||||
* \brief Create network interface base to IDLE state.
|
||||
* \param api Generates interface with PPP.
|
||||
* \param interface_name_ptr String pointer to interface name. Need to end to '\0' character.
|
||||
* Max length 32 characters including NULL at end. Note: the given name is not copied,
|
||||
* so it must remain valid as long as the interface is.
|
||||
*
|
||||
* \return >=0 Interface ID (0-127). Application needs to save this information.
|
||||
* \return -1 api was NULL.
|
||||
* \return -2 PPP is not supported at this build.
|
||||
* \return -3 No memory for the interface.
|
||||
*/
|
||||
extern int8_t arm_nwk_interface_ppp_init(struct eth_mac_api_s *api, const char *interface_name_ptr);
|
||||
|
||||
/**
|
||||
* \brief Set IPv6 interface setup.
|
||||
*
|
||||
|
@ -921,6 +937,37 @@ extern int8_t arm_network_trusted_certificate_add(const arm_certificate_entry_s
|
|||
*/
|
||||
extern int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* Remove trusted certificates
|
||||
*
|
||||
* This is used to remove all trusted root or intermediate certificates.
|
||||
*
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_trusted_certificates_remove(void);
|
||||
|
||||
/**
|
||||
* Add own certificate
|
||||
*
|
||||
* This is used to add own certificate and private key.
|
||||
* In case intermediate certificates are used, function can be called several times. Each call
|
||||
* to the function adds a certificate to own certificate chain.
|
||||
* Certificates are in bottom up order i.e. the top certificate is given last.
|
||||
*
|
||||
* \param cert Certificate.
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_own_certificate_add(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* Remove own certificates
|
||||
*
|
||||
* This is used to remove own certificates (chain).
|
||||
*
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_own_certificates_remove(void);
|
||||
|
||||
/**
|
||||
* Add Certificate Revocation List
|
||||
*
|
||||
|
@ -1060,6 +1107,34 @@ extern void net_get_version_information(uint8_t *ptr);
|
|||
|
||||
extern int arm_nwk_sleepy_device_parent_buffer_size_set(int8_t interface_id, uint16_t big_packet_threshold, uint16_t small_packets_per_child_count, uint16_t big_packets_total_count);
|
||||
|
||||
/**
|
||||
* \brief Set CCA threshold.
|
||||
*
|
||||
* This function can be used to set CCA threshold to PHY layer. Threshold is given as percentage of maximum threshold.
|
||||
* 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold.
|
||||
*
|
||||
* Note! Software MAC must be created and registered before using this function.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param cca_threshold CCA threshold (%).
|
||||
* \return 0 on success, <0 on errors.
|
||||
*/
|
||||
extern int8_t arm_nwk_set_cca_threshold(int8_t interface_id, uint8_t cca_threshold);
|
||||
|
||||
/**
|
||||
* \brief Set TX output power.
|
||||
*
|
||||
* This function can be used to set TX output power to PHY layer. TX power is given as percentage of maximum output power.
|
||||
* 0 is the lowest possible TX power and 100 is the highest possible TX power.
|
||||
*
|
||||
* Note! Software MAC must be created and registered before using this function.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param tx_power TX output power (%).
|
||||
* \return 0 on success, <0 on errors.
|
||||
*/
|
||||
extern int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -76,8 +76,10 @@ typedef enum {
|
|||
PHY_EXTENSION_GET_TIMESTAMP, /**< Read 32-bit constant monotonic time stamp in us */
|
||||
PHY_EXTENSION_SET_CSMA_PARAMETERS, /**< CSMA parameter's are given by phy_csma_params_t structure remember type cast uint8_t pointer to structure type*/
|
||||
PHY_EXTENSION_GET_SYMBOLS_PER_SECOND, /**< Read Symbols per seconds which will help to convert symbol time to real time */
|
||||
PHY_EXTENSION_SET_RF_CONFIGURATION, /**< Set RF configuration using phy_rf_channel_parameters_s structure */
|
||||
PHY_EXTENSION_FILTERING_SUPPORT /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */
|
||||
PHY_EXTENSION_SET_RF_CONFIGURATION, /**< Set RF configuration using phy_rf_channel_configuration_s structure */
|
||||
PHY_EXTENSION_FILTERING_SUPPORT, /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */
|
||||
PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */
|
||||
PHY_EXTENSION_SET_CCA_THRESHOLD /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */
|
||||
} phy_extension_type_e;
|
||||
|
||||
/** Address types */
|
||||
|
@ -95,6 +97,7 @@ typedef enum phy_link_type_e {
|
|||
PHY_LINK_15_4_SUBGHZ_TYPE, /**< Standard 802.15.4 subGHz radio 868 /915MHz. */
|
||||
PHY_LINK_TUN, /**< Tunnel interface for Linux TUN, RF network driver over serial bus or just basic application to application data flow. */
|
||||
PHY_LINK_SLIP, /**< Generic SLIP driver which just forward SLIP payload */
|
||||
PHY_LINK_PPP, /**< PPP */
|
||||
} phy_link_type_e;
|
||||
|
||||
/** Data layers */
|
||||
|
@ -184,6 +187,13 @@ typedef struct phy_device_channel_page_s {
|
|||
const phy_rf_channel_configuration_s *rf_channel_configuration; ///< Pointer to channel configuration
|
||||
} phy_device_channel_page_s;
|
||||
|
||||
/** PHY statistics */
|
||||
typedef struct phy_rf_statistics_s {
|
||||
uint32_t crc_fails; ///< CRC failures
|
||||
uint32_t tx_timeouts; ///< transmission timeouts
|
||||
uint32_t rx_timeouts; ///< reception timeouts
|
||||
} phy_rf_statistics_s;
|
||||
|
||||
/** Virtual data request */
|
||||
typedef struct virtual_data_req_s {
|
||||
uint16_t parameter_length; /**< Length of user specified header. Can be zero. */
|
||||
|
@ -283,6 +293,7 @@ typedef struct phy_device_driver_s {
|
|||
arm_net_virtual_config_tx_fn *virtual_config_tx_cb; /**< Virtual config send callback. Initialized by \ref arm_net_phy_register(). */
|
||||
arm_net_virtual_confirmation_rx_fn *virtual_confirmation_rx_cb; /**< Virtual confirmation receive callback. Initialized by \ref arm_net_phy_register(). */
|
||||
uint16_t tunnel_type; /**< Tun driver type. */
|
||||
phy_rf_statistics_s *phy_rf_statistics; /**< PHY statistics. */
|
||||
} phy_device_driver_s;
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ struct mac_api_s;
|
|||
struct mac_description_storage_size_s;
|
||||
struct fhss_api;
|
||||
struct mac_statistics_s;
|
||||
struct phy_rf_statistics_s;
|
||||
|
||||
/**
|
||||
* @brief Creates 802.15.4 MAC API instance which will use RF driver given
|
||||
|
@ -81,6 +82,14 @@ 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 Start collecting statistics from PHY driver.
|
||||
* @param mac_api MAC instance.
|
||||
* @param phy_statistics Statistics storage.
|
||||
* @return 0 on success, -1 on fail.
|
||||
*/
|
||||
extern int ns_sw_mac_phy_statistics_start(struct mac_api_s *mac_api, struct phy_rf_statistics_s *phy_statistics);
|
||||
|
||||
/**
|
||||
* @brief Read current timestamp.
|
||||
* @param mac_api MAC instance.
|
||||
|
|
|
@ -148,6 +148,39 @@
|
|||
/** Energy List TLV. */
|
||||
#define MESHCOP_TLV_ENERGY_LIST 57
|
||||
|
||||
/** Thread 1.2 */
|
||||
|
||||
/** Timeout TLV. */
|
||||
#define MESHCOP_TLV_TIMEOUT 58
|
||||
|
||||
/** Thread domain name TLV. */
|
||||
#define MESHCOP_TLV_DOMAIN_NAME 59
|
||||
|
||||
/** Domain prefix TLV TLV.*/
|
||||
#define MESHCOP_TLV_DOMAIN_PREFIX 60
|
||||
|
||||
/** AE Steering Data TLV. */
|
||||
#define MESHCOP_TLV_AE_STEERING_DATA 61
|
||||
|
||||
/** NMKP Steering Data TLV. */
|
||||
#define MESHCOP_TLV_NMKP_STEERING_DATA 62
|
||||
|
||||
/** Commissioner Token TLV. */
|
||||
#define MESHCOP_TLV_COMM_TOKEN 63
|
||||
|
||||
/** Commissioner Signature TLV. */
|
||||
#define MESHCOP_TLV_COMM_SIGNATURE 64
|
||||
|
||||
/** NMKP Steering Data TLV. */
|
||||
#define MESHCOP_TLV_AE_PORT 65
|
||||
|
||||
/** NMKP Steering Data TLV. */
|
||||
#define MESHCOP_TLV_NMKP_PORT 66
|
||||
|
||||
/** Registrar IPV6 address. */
|
||||
#define MESHCOP_TLV_REGISTRAR_IPV6_ADDRESS 68
|
||||
|
||||
|
||||
/** Discovery Request TLV. */
|
||||
#define MESHCOP_TLV_DISCOVERY_REQUEST 128
|
||||
/** Discovery response TLV. */
|
||||
|
|
|
@ -49,21 +49,21 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
|||
* Border router configuration options
|
||||
*/
|
||||
#define BBR_ULA_C 0x0001 /**< Static ULA prefix created automatically */
|
||||
#define BBR_GUA_C 0x0002 /**< Routable prefix is learned from the backbone */
|
||||
#define BBR_GUA_ROUTE 0x0004 /**< More specific route is added for GUA prefix */
|
||||
#define BBR_GUA_SLAAC 0x0008 /**< Use SLAAC addressing in routable prefix */
|
||||
#define BBR_GUA_WAIT 0x0010 /**< Wait backbone availability before starting RPL dodag */
|
||||
#define BBR_BB_WAIT 0x0020 /**< Wait backbone availability before starting Wi-SUN network */
|
||||
#define BBR_GUA_ROUTE 0x0002 /**< More specific route is added for GUA prefix */
|
||||
#define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */
|
||||
|
||||
/*Deprecated configuration values */
|
||||
#define BBR_GUA_C 0x0000 /**< Routable prefix is learned from the backbone */
|
||||
#define BBR_GUA_SLAAC 0x0000 /**< Use SLAAC addressing in routable prefix */
|
||||
#define BBR_GUA_WAIT 0x0000 /**< Wait backbone availability before startingRPL dodag */
|
||||
|
||||
/**
|
||||
* Configure border router features.
|
||||
*
|
||||
* \param interface_id interface ID of the Wi-SUN network
|
||||
* \param options Options configured to Border router
|
||||
* BBR_ULA_C Configure Mesh local ULA prefix with SLAAC address (default)
|
||||
* BBR_GUA_C Configure GUA/ULA prefix from backbone to RPL (default)
|
||||
* BBR_GUA_ROUTE Add more specific route for GUA (default)
|
||||
* BBR_GUA_SLAAC Use SLAAC address generation in GUA prefix
|
||||
* BBR_GUA_WAIT Start RPL root only when GUA is available
|
||||
* BBR_ULA_C Configure Mesh local ULA prefix with SLAAC address
|
||||
* BBR_GUA_ROUTE Add more specific route for GUA
|
||||
* BBR_BB_WAIT Start Wi-SUN network only when backbone is ready
|
||||
*
|
||||
* By default Wi-SUN network is started and is treated as separate interface even if backbone is not available.
|
||||
|
|
|
@ -115,6 +115,22 @@ int ws_management_node_init(
|
|||
char *network_name_ptr,
|
||||
fhss_timer_t *fhss_timer_ptr);
|
||||
|
||||
/**
|
||||
* Change the network name
|
||||
*
|
||||
* Change the network name dynamically at a runtime.
|
||||
* If stack is running the network discovery is restarted.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param network_name_ptr Nul terminated Network name limited to 32 characters.
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
int ws_management_network_name_set(
|
||||
int8_t interface_id,
|
||||
char *network_name_ptr);
|
||||
|
||||
/**
|
||||
* Configure regulatory domain of Wi-SUN stack.
|
||||
*
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_ADDRESS_REGISTRATION_CLIENT_H_
|
||||
#define THREAD_ADDRESS_REGISTRATION_CLIENT_H_
|
||||
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
void thread_address_registration_init(void);
|
||||
bool thread_address_registration_running(void);
|
||||
void thread_address_registration_deinit(void);
|
||||
|
||||
void thread_address_registration_timer_set(protocol_interface_info_entry_t *interface, uint16_t dua_delay_seconds, uint16_t mlr_refresh_seconds);
|
||||
void thread_address_registration_timer(protocol_interface_info_entry_t *interface, uint16_t seconds);
|
||||
#else
|
||||
|
||||
#define thread_address_registration_init(void)
|
||||
#define thread_address_registration_running(void)
|
||||
#define thread_address_registration_deinit(void)
|
||||
|
||||
#define thread_address_registration_timer_set(interface, dua_delay_seconds, mlr_refresh_seconds);
|
||||
#define thread_address_registration_timer(interface, seconds);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* THREAD_ADDRESS_REGISTRATION_CLIENT_H_ */
|
|
@ -51,8 +51,7 @@
|
|||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
|
@ -696,7 +695,7 @@ static void thread_bbr_status_check(thread_bbr_t *this, uint32_t seconds)
|
|||
//If there is a default router present in any prefix other than us we do not forward multicast
|
||||
//This prevents multicasts to different interfaces where Thread Mesh is forwarder
|
||||
bool forward_multicast = !thread_bbr_default_route_exists(cur, NULL);
|
||||
thread_extension_bbr_mcast_fwd_check(cur->id, &forward_multicast);
|
||||
thread_bbr_commercial_mcast_fwd_check(cur->id, &forward_multicast);
|
||||
|
||||
thread_bbr_routing_enable(this, forward_multicast);
|
||||
} else {
|
||||
|
@ -794,7 +793,7 @@ void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
|
|||
{
|
||||
(void)cur;
|
||||
thread_mdns_network_data_update_notify();
|
||||
thread_extension_bbr_route_update(cur);
|
||||
thread_bbr_commercial_route_update(cur);
|
||||
}
|
||||
#endif /* HAVE_THREAD_BORDER_ROUTER*/
|
||||
|
||||
|
@ -980,10 +979,7 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t seconds)
|
|||
thread_bbr_status_check(this, seconds);
|
||||
}
|
||||
|
||||
if (!thread_extension_version_check(thread_version)) {
|
||||
return;
|
||||
}
|
||||
thread_extension_bbr_seconds_timer(interface_id, seconds);
|
||||
thread_bbr_commercial_seconds_timer(interface_id, seconds);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -996,6 +992,10 @@ int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
|
|||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
// Send NA only if it is enabled for the backhaul
|
||||
if (!cur->send_na) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
|
||||
protocol_push(buffer);
|
||||
|
@ -1150,7 +1150,7 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id)
|
|||
THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LONG_TERM,
|
||||
THREAD_BBR_IPV6_NEIGHBOUR_CACHE_LIFETIME);
|
||||
|
||||
thread_extension_bbr_init(interface_id, backbone_interface_id);
|
||||
thread_bbr_commercial_init(interface_id, backbone_interface_id);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
@ -1165,7 +1165,7 @@ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t tim
|
|||
(void) timeout_b;
|
||||
(void) delay;
|
||||
#ifdef HAVE_THREAD_BORDER_ROUTER
|
||||
thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay);
|
||||
thread_bbr_commercial_timeout_set(interface_id, timeout_a, timeout_b, delay);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
|
@ -1178,7 +1178,7 @@ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix)
|
|||
(void) interface_id;
|
||||
(void) prefix;
|
||||
#ifdef HAVE_THREAD_BORDER_ROUTER
|
||||
return thread_extension_bbr_prefix_set(interface_id, prefix);
|
||||
return thread_bbr_commercial_prefix_set(interface_id, prefix);
|
||||
#else
|
||||
return -1;
|
||||
#endif // HAVE_THREAD_BORDER_ROUTER
|
||||
|
@ -1189,7 +1189,7 @@ int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number)
|
|||
(void) interface_id;
|
||||
(void) sequence_number;
|
||||
#ifdef HAVE_THREAD_BORDER_ROUTER
|
||||
return thread_extension_bbr_sequence_number_set(interface_id, sequence_number);
|
||||
return thread_bbr_commercial_sequence_number_set(interface_id, sequence_number);
|
||||
#else
|
||||
return -1;
|
||||
#endif // HAVE_THREAD_BORDER_ROUTER
|
||||
|
@ -1201,7 +1201,7 @@ int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8
|
|||
(void) addr_ptr;
|
||||
(void) port;
|
||||
#ifdef HAVE_THREAD_BORDER_ROUTER
|
||||
return thread_extension_bbr_address_set(interface_id, addr_ptr, port);
|
||||
return thread_bbr_commercial_address_set(interface_id, addr_ptr, port);
|
||||
#else
|
||||
return -1;
|
||||
#endif // HAVE_THREAD_BORDER_ROUTER
|
||||
|
@ -1217,7 +1217,7 @@ void thread_bbr_stop(int8_t interface_id)
|
|||
if (!this) {
|
||||
return;
|
||||
}
|
||||
thread_extension_bbr_delete(interface_id);
|
||||
thread_bbr_commercial_delete(interface_id);
|
||||
thread_bbr_network_data_remove(this);
|
||||
thread_bbr_routing_disable(this);
|
||||
thread_border_router_publish(interface_id);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Thread 1.2 primary border router support.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_BBR_COMMERCIAL_H_
|
||||
#define THREAD_BBR_COMMERCIAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Thread PBBR ML-EID map structure
|
||||
*/
|
||||
typedef struct thread_pbbr_dua_info {
|
||||
uint8_t mleid_ptr[8];
|
||||
uint32_t last_contact_time;
|
||||
} thread_pbbr_dua_info_t;
|
||||
|
||||
#if defined(HAVE_THREAD_V2) && defined(HAVE_THREAD_BORDER_ROUTER)
|
||||
int8_t thread_bbr_commercial_init(int8_t interface_id, int8_t backbone_interface_id);
|
||||
void thread_bbr_commercial_delete(int8_t interface_id);
|
||||
bool thread_bbr_commercial_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc);
|
||||
void thread_bbr_commercial_seconds_timer(int8_t interface_id, uint32_t seconds);
|
||||
int thread_bbr_commercial_sequence_number_set(int8_t interface_id, uint8_t seq_number);
|
||||
int thread_bbr_commercial_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
|
||||
int thread_bbr_commercial_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port);
|
||||
void thread_bbr_commercial_route_update(protocol_interface_info_entry_t *cur);
|
||||
int thread_bbr_commercial_prefix_set(int8_t interface_id, uint8_t *prefix);
|
||||
void thread_bbr_commercial_old_partition_data_clean(int8_t interface_id);
|
||||
void thread_bbr_commercial_status_override_get(uint8_t *dua_status, uint8_t *dua_count, uint8_t *ba_failure_count);
|
||||
void thread_bbr_commercial_status_override_set(uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count);
|
||||
void thread_bbr_commercial_mcast_fwd_check(int8_t interface_id, bool *multicast_fwd);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define thread_bbr_commercial_init(interface_id, backbone_interface_id)
|
||||
#define thread_bbr_commercial_delete(interface_id)
|
||||
#define thread_bbr_commercial_nd_query_process(cur, target_addr, rloc) false
|
||||
#define thread_bbr_commercial_seconds_timer(interface_id, seconds)
|
||||
#define thread_bbr_commercial_timeout_set(interface_id, timeout_a, timeout_b, delay)
|
||||
#define thread_bbr_commercial_address_set(interface_id, addr_ptr, port) (-1)
|
||||
#define thread_bbr_commercial_route_update(cur)
|
||||
#define thread_bbr_commercial_sequence_number_set(interface_id, seq_number) (-1)
|
||||
#define thread_bbr_commercial_prefix_set(interface_id, prefix) 0
|
||||
#define thread_bbr_commercial_old_partition_data_clean(interface_id)
|
||||
#define thread_bbr_commercial_status_override_get(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_bbr_commercial_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_bbr_commercial_mcast_fwd_check(interface_id, multicast_fwd)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //THREAD_BBR_COMMERCIAL_H_
|
|
@ -48,6 +48,7 @@
|
|||
#include "libDHCPv6/libDHCPv6.h"
|
||||
#include "libDHCPv6/libDHCPv6_server.h"
|
||||
#include "ns_trace.h"
|
||||
#include "coap_service_api.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_routing.h"
|
||||
|
@ -63,16 +64,14 @@
|
|||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_network_synch.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
#include "6LoWPAN/Thread/thread_address_registration_client.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_border_router_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_beacon.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/Thread/thread_mle_message_handler.h"
|
||||
#include "mac_api.h"
|
||||
|
@ -120,7 +119,20 @@ static void thread_bootsrap_network_discovery_failure(int8_t interface_id);
|
|||
static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
|
||||
static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info);
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
static bool enabled = false;
|
||||
static uint32_t addr_notificastion_timer;
|
||||
static uint32_t mlr_timer;
|
||||
|
||||
static void thread_bootstrap_pbbr_network_data_process(struct protocol_interface_info_entry *cur);
|
||||
static void thread_bootstrap_pbbr_update_done(struct protocol_interface_info_entry *cur);
|
||||
|
||||
#else
|
||||
#define thread_bootstrap_pbbr_network_data_process(cur)
|
||||
#define thread_bootstrap_pbbr_update_done(cur)
|
||||
|
||||
#endif
|
||||
|
||||
static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
|
||||
{
|
||||
|
@ -354,7 +366,7 @@ int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uin
|
|||
|
||||
/*Rule 0: If we are going to form Higher partition than heard we dont try to attach to lower ones
|
||||
*/
|
||||
if (thread_extension_enabled(cur) &&
|
||||
if (thread_common_ccm_enabled(cur) &&
|
||||
thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
|
||||
if (heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) {
|
||||
tr_debug("Heard a lower weight partition");
|
||||
|
@ -692,7 +704,7 @@ int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, l
|
|||
//Define Default Contexts
|
||||
lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true);
|
||||
|
||||
thread_extension_bbr_route_update(cur);
|
||||
thread_bbr_commercial_route_update(cur);
|
||||
|
||||
blacklist_clear();
|
||||
|
||||
|
@ -890,7 +902,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur)
|
|||
dhcp_client_init(cur->id);
|
||||
dhcp_client_configure(cur->id, false, false, false);
|
||||
thread_management_client_init(cur->id);
|
||||
thread_address_registration_init();
|
||||
thread_bootstrap_address_registration_init();
|
||||
cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT;
|
||||
cur->mpl_seed_set_entry_lifetime = 90;
|
||||
cur->mpl_proactive_forwarding = true;
|
||||
|
@ -1914,7 +1926,7 @@ static void thread_network_select(struct protocol_interface_info_entry *interfac
|
|||
{
|
||||
(void) interface_ptr;
|
||||
|
||||
discovery_response_list_t *discovered_network_ptr = thread_extension_bootstrap_network_select(interface_ptr, discover_response);
|
||||
discovery_response_list_t *discovered_network_ptr = thread_ccm_network_select(interface_ptr, discover_response);
|
||||
|
||||
/* If network found */
|
||||
if (discovered_network_ptr) {
|
||||
|
@ -2118,7 +2130,7 @@ static void thread_bootsrap_network_join_start(struct protocol_interface_info_en
|
|||
tr_debug("Start commission with %s", trace_ipv6(parentLLAddress));
|
||||
cur_interface->bootsrap_state_machine_cnt = 0;
|
||||
|
||||
if (0 > thread_extension_bootstrap_commission_start(cur_interface, parentLLAddress, nwk_info, thread_bootstrap_joiner_application_commission_done_cb)) {
|
||||
if (0 > thread_ccm_commission_start(cur_interface, parentLLAddress, nwk_info, thread_bootstrap_joiner_application_commission_done_cb)) {
|
||||
thread_joiner_application_pskd_commission_start(cur_interface->id, parentLLAddress, nwk_info->joiner_port, nwk_info->pan_id, nwk_info->extented_pan_id, nwk_info->channel, thread_bootstrap_joiner_application_commission_done_cb);
|
||||
}
|
||||
ns_dyn_mem_free(nwk_info);
|
||||
|
@ -2319,7 +2331,7 @@ void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
|
|||
}
|
||||
void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
thread_address_registration_deinit();
|
||||
thread_bootstrap_address_registration_deinit();
|
||||
thread_anycast_address_policy_update(cur->thread_info, false);
|
||||
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL);
|
||||
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
|
||||
|
@ -2742,7 +2754,7 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur)
|
|||
thread_router_bootstrap_anycast_address_register(cur);
|
||||
// Update joiner router status
|
||||
thread_management_server_joiner_router_init(cur->id);
|
||||
thread_extension_service_init(cur);
|
||||
thread_management_server_ccm_service_init(cur->id);
|
||||
|
||||
// Update border router relay
|
||||
thread_bbr_commissioner_proxy_service_update(cur->id);
|
||||
|
@ -2750,7 +2762,7 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur)
|
|||
thread_beacon_create_payload(cur);
|
||||
|
||||
// Indicate network data change to other modules
|
||||
thread_extension_network_data_process(cur);
|
||||
thread_bootstrap_pbbr_network_data_process(cur);
|
||||
thread_border_router_network_data_update_notify(cur);
|
||||
thread_bbr_network_data_update_notify(cur);
|
||||
|
||||
|
@ -2897,7 +2909,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
|
|||
// generate address based on res1 bit
|
||||
if (curBorderRouter->P_res1) {
|
||||
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
|
||||
thread_extension_dua_address_generate(cur, curPrefix->servicesPrefix, 64);
|
||||
thread_bootstrap_dua_address_generate(cur, curPrefix->servicesPrefix, 64);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3039,4 +3051,426 @@ bool thread_bootstrap_should_register_address(protocol_interface_info_entry_t *c
|
|||
return (mode & MLE_DEV_MASK) == MLE_RFD_DEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread 1.2 support
|
||||
*/
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
static void thread_bootstrap_mcast_subscrition_change(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
uint8_t *addr;
|
||||
uint8_t *ptr;
|
||||
uint8_t addr_len;
|
||||
uint8_t br_ml_addr[16];
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(interface, br_ml_addr, NULL, NULL, NULL)) {
|
||||
return;
|
||||
}
|
||||
addr = ns_dyn_mem_temporary_alloc(16 * thread_max_mcast_addr + 2);
|
||||
if (!addr) {
|
||||
return;
|
||||
}
|
||||
// MLR is sent only for primary BBR for now, but this might change
|
||||
ptr = addr;
|
||||
addr_len = 0;
|
||||
*ptr++ = TMFCOP_TLV_IPV6_ADDRESS;
|
||||
*ptr++ = 0; // Length will be updated later
|
||||
ns_list_foreach(if_group_entry_t, cur, &interface->ip_groups) {
|
||||
if (addr_ipv6_multicast_scope(cur->group) < IPV6_SCOPE_ADMIN_LOCAL) {
|
||||
continue;
|
||||
}
|
||||
if (addr_ipv6_equal(cur->group, ADDR_SITE_LOCAL_ALL_ROUTERS)) {
|
||||
continue;
|
||||
}
|
||||
memcpy(ptr, cur->group, 16);
|
||||
ptr += 16;
|
||||
addr_len = ptr - addr;
|
||||
addr[1] = addr_len - 2;// Fill in the length
|
||||
if (addr_len > 16 * thread_max_mcast_addr) {
|
||||
// Send first patch
|
||||
thread_management_client_mlr_req_send(interface->id, br_ml_addr, addr, addr_len);
|
||||
// Reset the packet to start
|
||||
ptr = addr;
|
||||
ptr += 2;
|
||||
addr_len = 0;
|
||||
}
|
||||
}
|
||||
if (addr_len != 0) {
|
||||
// Send rest
|
||||
thread_management_client_mlr_req_send(interface->id, br_ml_addr, addr, addr_len);
|
||||
}
|
||||
ns_dyn_mem_free(addr);
|
||||
}
|
||||
static int thread_bootstrap_dua_registration_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
|
||||
uint16_t addr_len;
|
||||
uint8_t bbr_status;
|
||||
uint8_t *addr_data_ptr = NULL;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_client_get_interface_id_by_service_id(service_id));
|
||||
|
||||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!response_ptr) {
|
||||
tr_warn("DUA.resp failed");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_STATUS, &bbr_status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_TARGET_EID, &addr_data_ptr);
|
||||
|
||||
if (addr_len < 16) {
|
||||
tr_warn("Invalid target eid in DUA.rsp cb message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if_address_entry_t *addr_entry = addr_get_entry(cur, addr_data_ptr);
|
||||
if (addr_entry) {
|
||||
// Own processing
|
||||
if (bbr_status == THREAD_ST_DUA_SUCCESS) {
|
||||
addr_entry->preferred_lifetime = 0xffffffff;
|
||||
} else if (bbr_status == THREAD_ST_DUA_DUPLICATE) {
|
||||
cur->dad_failures++;
|
||||
thread_bootstrap_dua_address_generate(cur, addr_data_ptr, 64);
|
||||
} else if (bbr_status == THREAD_ST_DUA_INVALID) {
|
||||
addr_delete(cur, addr_data_ptr);
|
||||
} else {
|
||||
addr_entry->preferred_lifetime = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// processing for MTD children
|
||||
ipv6_neighbour_t *neighbour_entry;
|
||||
uint16_t nce_short_addr;
|
||||
uint8_t destination_address[16] = {0};
|
||||
|
||||
if (bbr_status == THREAD_ST_DUA_SUCCESS) {
|
||||
// registration successful
|
||||
return 0;
|
||||
}
|
||||
|
||||
neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, addr_data_ptr);
|
||||
if (!neighbour_entry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nce_short_addr = common_read_16_bit(neighbour_entry->ll_address + 2);
|
||||
if (!thread_addr_is_child(cur->thread_info->routerShortAddress, nce_short_addr)) {
|
||||
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bbr_status == THREAD_ST_DUA_DUPLICATE || bbr_status == THREAD_ST_DUA_INVALID) {
|
||||
// remove invalid or duplicate child entry
|
||||
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
|
||||
}
|
||||
|
||||
thread_addr_write_mesh_local_16(destination_address, nce_short_addr, cur->thread_info);
|
||||
|
||||
thread_management_client_addr_ntf_send(cur->id, destination_address, addr_data_ptr, bbr_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thread_bootstrap_dua_registration_send(protocol_interface_info_entry_t *cur, const uint8_t address[16], const uint8_t ml_eid[8], const uint8_t dst_addr[16])
|
||||
{
|
||||
|
||||
tr_debug("domain address registration (DUA.req send)");
|
||||
thread_bootstrap_pbbr_update_done(cur);
|
||||
|
||||
uint8_t payload[2 + 16 + 2 + 8];
|
||||
uint8_t *ptr;
|
||||
|
||||
ptr = payload;
|
||||
ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, address);
|
||||
ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_ML_EID, 8, ml_eid);
|
||||
|
||||
coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_NONE,
|
||||
dst_addr, THREAD_MANAGEMENT_PORT,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST,
|
||||
THREAD_URI_BBR_DOMAIN_ADDRESS_REGISTRATION, COAP_CT_OCTET_STREAM,
|
||||
payload, ptr - payload, thread_bootstrap_dua_registration_cb);
|
||||
}
|
||||
|
||||
static int thread_bootstrap_pbbr_update_needed(struct protocol_interface_info_entry *cur, uint16_t rloc, uint8_t seq)
|
||||
{
|
||||
if (!cur->thread_info->ccm_info) {
|
||||
return 0;
|
||||
}
|
||||
if (cur->thread_info->ccm_info->update_needed ||
|
||||
seq != cur->thread_info->ccm_info->sequence_number ||
|
||||
rloc != cur->thread_info->ccm_info->rloc) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thread_bootstrap_pbbr_update_done(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Check if network data changed or bbr info and send proactive an if needed
|
||||
uint8_t addr[16];
|
||||
uint8_t sequence_number;
|
||||
uint32_t delay_timer;
|
||||
uint32_t br_mlr_timer;
|
||||
if (!cur->thread_info->ccm_info) {
|
||||
return;
|
||||
}
|
||||
if (0 == thread_common_primary_bbr_get(cur, addr, &sequence_number, &br_mlr_timer, &delay_timer)) {
|
||||
// BBR updated
|
||||
cur->thread_info->ccm_info->rloc = common_read_16_bit(&addr[14]);
|
||||
cur->thread_info->ccm_info->sequence_number = sequence_number;
|
||||
cur->thread_info->ccm_info->delay_timer = delay_timer;
|
||||
cur->thread_info->ccm_info->mlr_timer = br_mlr_timer;
|
||||
cur->thread_info->ccm_info->update_needed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_bootstrap_pbbr_network_data_process(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Check if network data changed or bbr info and send proactive an if needed
|
||||
uint8_t addr[16];
|
||||
uint8_t sequence_number;
|
||||
uint32_t delay_timer;
|
||||
uint32_t mlr_timeout;
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(cur, addr, &sequence_number, &mlr_timeout, &delay_timer)) {
|
||||
// BBR not present
|
||||
return;
|
||||
}
|
||||
if (1 == thread_bootstrap_pbbr_update_needed(cur, common_read_16_bit(&addr[14]), sequence_number)) {
|
||||
thread_bootstrap_address_registration_timer_set(cur, 1 + randLIB_get_random_in_range(0, delay_timer / 1000), randLIB_get_random_in_range(1, 5));
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_bootstrap_address_registration_trigger(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
// Address notification is sent only for DUA address
|
||||
thread_bootstrap_pbbr_update_done(interface);
|
||||
// Send notification on behalf of children
|
||||
ns_list_foreach(ipv6_neighbour_t, n, &interface->ipv6_neighbour_cache.list) {
|
||||
if (n->type == IP_NEIGHBOUR_REGISTERED && addr_ipv6_scope(n->ip_address, interface) > IPV6_SCOPE_REALM_LOCAL) {
|
||||
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(interface), &n->ll_address[2], ADDR_802_15_4_SHORT);
|
||||
if (entry) {
|
||||
thread_bootstrap_address_registration(interface, n->ip_address, entry->mac64, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send own Address
|
||||
ns_list_foreach(if_address_entry_t, e, &interface->ip_addresses) {
|
||||
if (addr_ipv6_scope(e->address, interface) > IPV6_SCOPE_REALM_LOCAL) {
|
||||
thread_bootstrap_address_registration(interface, e->address, NULL, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void thread_bootstrap_address_registration_init()
|
||||
{
|
||||
enabled = true;
|
||||
addr_notificastion_timer = THREAD_PROACTIVE_AN_INTERVAL;
|
||||
mlr_timer = 0;
|
||||
}
|
||||
|
||||
bool thread_bootstrap_address_registration_running()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void thread_bootstrap_address_registration_deinit()
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
bool thread_bootstrap_is_domain_prefix(protocol_interface_info_entry_t *interface, const uint8_t *addr)
|
||||
{
|
||||
uint8_t address[16];
|
||||
memcpy(address, addr, 16);
|
||||
thread_prefix_tlv_t prefixTlv;
|
||||
prefixTlv.domainId = 0;
|
||||
prefixTlv.Prefix = address;
|
||||
prefixTlv.PrefixLen = 64;
|
||||
thread_network_data_prefix_cache_entry_t *prefix_entry = NULL;
|
||||
thread_network_data_cache_entry_t *networkDataCache = &interface->thread_info->networkDataStorage;
|
||||
prefix_entry = thread_prefix_entry_find(&networkDataCache->localPrefixList, &prefixTlv);
|
||||
if (!prefix_entry) {
|
||||
return false;
|
||||
}
|
||||
ns_list_foreach(thread_network_server_data_entry_t, brEntry, &prefix_entry->borderRouterList) {
|
||||
if (brEntry->P_res1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void thread_bootstrap_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len)
|
||||
{
|
||||
if_address_entry_t *def_address = NULL;
|
||||
uint8_t domain_address[16];
|
||||
if (thread_info(cur)->version < THREAD_VERSION_1_2) {
|
||||
return;
|
||||
}
|
||||
addr_delete_matching(cur, NULL, 0, ADDR_SOURCE_THREAD_DOMAIN);
|
||||
memcpy(domain_address, domain_prefix, 8);
|
||||
def_address = icmpv6_slaac_address_add(cur, domain_address, domain_prefix_len, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT);
|
||||
if (def_address) {
|
||||
tr_info("Generated domain address 64: %s", trace_ipv6(def_address->address));
|
||||
def_address->source = ADDR_SOURCE_THREAD_DOMAIN;
|
||||
} else {
|
||||
tr_error("Domain address creation failed");
|
||||
}
|
||||
}
|
||||
|
||||
void thread_bootstrap_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected)
|
||||
{
|
||||
uint8_t *ml_eid;
|
||||
uint8_t br_ml_addr[16];
|
||||
uint8_t seq;
|
||||
uint32_t delay_timer;
|
||||
|
||||
if (thread_info(interface)->version < THREAD_VERSION_1_2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!thread_bootstrap_is_domain_prefix(interface, addr)) {
|
||||
return;
|
||||
}
|
||||
tr_debug("domain prefix address");
|
||||
if (0 != thread_common_primary_bbr_get(interface, br_ml_addr, &seq, &delay_timer, NULL)) {
|
||||
// No pBBR present
|
||||
return;
|
||||
}
|
||||
tr_info("domain prefix Primary bbr present");
|
||||
|
||||
if (child_mac64) {
|
||||
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(interface), child_mac64, ADDR_802_15_4_LONG);
|
||||
|
||||
if (!entry) {
|
||||
tr_error("No MLE entry.");
|
||||
return;
|
||||
}
|
||||
|
||||
ml_eid = thread_neighbor_class_get_mleid(&interface->thread_info->neighbor_class, entry->index);
|
||||
if (!ml_eid) {
|
||||
tr_error("No Thread neighbor.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (duplicate_child_detected) {
|
||||
uint8_t dest_address[16] = {0};
|
||||
thread_addr_write_mesh_local_16(dest_address, entry->mac16, interface->thread_info);
|
||||
thread_management_client_addr_ntf_send(interface->id, dest_address, addr, 3);
|
||||
return;
|
||||
}
|
||||
if (!refresh_child_entry) {
|
||||
// don't send n/dr for existing entry
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
link_configuration_s *link_config = thread_joiner_application_get_config(interface->id);
|
||||
|
||||
if (!link_config) {
|
||||
tr_error("No link configuration.");
|
||||
return;
|
||||
}
|
||||
ml_eid = thread_joiner_application_ml_eid_get(interface->id);
|
||||
}
|
||||
|
||||
// Register the DUA address
|
||||
thread_bootstrap_dua_registration_send(interface, addr, ml_eid, br_ml_addr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void thread_bootstrap_address_registration_timer_set(protocol_interface_info_entry_t *interface, uint16_t dua_delay_seconds, uint16_t mlr_refresh_seconds)
|
||||
{
|
||||
(void)interface;
|
||||
if (dua_delay_seconds != 0) {
|
||||
addr_notificastion_timer = dua_delay_seconds;
|
||||
}
|
||||
if (mlr_refresh_seconds != 0) {
|
||||
mlr_timer = mlr_refresh_seconds;
|
||||
}
|
||||
|
||||
}
|
||||
void thread_bootstrap_address_registration_timer(protocol_interface_info_entry_t *interface, uint16_t seconds)
|
||||
{
|
||||
uint32_t mlr_timeout;
|
||||
uint32_t delay_timer;
|
||||
if (!enabled || interface->thread_info->version < THREAD_VERSION_1_2) {
|
||||
return;
|
||||
}
|
||||
if (thread_bootstrap_should_register_address(interface)) {
|
||||
if (!interface->thread_info->thread_endnode_parent) {
|
||||
// We dont have parent so skip
|
||||
return;
|
||||
}
|
||||
if (interface->thread_info->thread_endnode_parent->version >= THREAD_VERSION_1_2) {
|
||||
// Parent supports all features
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(interface, NULL, NULL, &mlr_timeout, &delay_timer)) {
|
||||
// BBR not present
|
||||
return;
|
||||
}
|
||||
/* Update multicast addresses */
|
||||
if (mlr_timer > seconds) {
|
||||
mlr_timer -= seconds;
|
||||
} else {
|
||||
mlr_timer = mlr_timeout - randLIB_get_random_in_range(30, 50);
|
||||
thread_bootstrap_mcast_subscrition_change(interface);
|
||||
}
|
||||
/* Update global scope addresses (children's as well) */
|
||||
if (addr_notificastion_timer > seconds) {
|
||||
addr_notificastion_timer -= seconds;
|
||||
} else {
|
||||
addr_notificastion_timer = THREAD_PROACTIVE_AN_INTERVAL + randLIB_get_random_in_range(0, delay_timer / 1000);
|
||||
thread_bootstrap_address_registration_trigger(interface);
|
||||
}
|
||||
|
||||
}
|
||||
void thread_bootstrap_child_address_registration_response_process(struct protocol_interface_info_entry *interface)
|
||||
{
|
||||
// if we are version 3 and parent is lower we need to send registrations for them
|
||||
|
||||
if (interface->thread_info->version < THREAD_VERSION_1_2) {
|
||||
thread_bootstrap_address_registration_deinit();
|
||||
return;
|
||||
}
|
||||
if (!interface->thread_info->thread_endnode_parent) {
|
||||
// We dont have parent return
|
||||
thread_bootstrap_address_registration_deinit();
|
||||
return;
|
||||
}
|
||||
if (interface->thread_info->thread_endnode_parent->version >= THREAD_VERSION_1_2) {
|
||||
//parent supports 1.2
|
||||
thread_bootstrap_address_registration_deinit();
|
||||
return;
|
||||
}
|
||||
// We will start address registration timers
|
||||
if (!thread_bootstrap_address_registration_running()) {
|
||||
uint32_t dua_delay;
|
||||
if (0 != thread_common_primary_bbr_get(interface, NULL, NULL, NULL, &dua_delay)) {
|
||||
dua_delay = randLIB_get_random_in_range(1, 5);
|
||||
}
|
||||
thread_bootstrap_address_registration_init();
|
||||
thread_bootstrap_address_registration_timer_set(interface, 1 + randLIB_get_random_in_range(0, dua_delay / 1000), randLIB_get_random_in_range(1, 5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -205,4 +205,28 @@ void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uin
|
|||
|
||||
#endif // HAVE_THREAD
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
void thread_bootstrap_address_registration_init(void);
|
||||
bool thread_bootstrap_address_registration_running(void);
|
||||
void thread_bootstrap_address_registration_deinit(void);
|
||||
bool thread_bootstrap_is_domain_prefix(protocol_interface_info_entry_t *interface, const uint8_t *addr);
|
||||
void thread_bootstrap_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len);
|
||||
void thread_bootstrap_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected);
|
||||
void thread_bootstrap_child_address_registration_response_process(struct protocol_interface_info_entry *interface);
|
||||
void thread_bootstrap_address_registration_timer_set(protocol_interface_info_entry_t *interface, uint16_t dua_delay_seconds, uint16_t mlr_refresh_seconds);
|
||||
void thread_bootstrap_address_registration_timer(protocol_interface_info_entry_t *interface, uint16_t seconds);
|
||||
#else
|
||||
|
||||
#define thread_bootstrap_address_registration_init()
|
||||
#define thread_bootstrap_address_registration_running() ((void)0)
|
||||
#define thread_bootstrap_address_registration_deinit()
|
||||
#define thread_bootstrap_is_domain_prefix(interface, addr) ((void)0)
|
||||
#define thread_bootstrap_dua_address_generate(cur, domain_prefix, domain_prefix_len)
|
||||
#define thread_bootstrap_address_registration(interface, addr, child_mac64, refresh_child_entry, duplicate_child_detected)
|
||||
#define thread_bootstrap_child_address_registration_response_process(interface)
|
||||
#define thread_bootstrap_address_registration_timer_set(interface, dua_delay_seconds, mlr_refresh_seconds)
|
||||
#define thread_bootstrap_address_registration_timer(interface, seconds)
|
||||
|
||||
#endif
|
||||
#endif /* THREAD_BOOTSTRAP_H_ */
|
||||
|
|
|
@ -42,13 +42,13 @@
|
|||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/Thread/thread_config.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_storage.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_border_router_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "6LoWPAN/Thread/thread_mdns.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
|
@ -599,7 +599,7 @@ void thread_border_router_old_partition_data_clean(int8_t interface_id)
|
|||
if (this) {
|
||||
coap_service_request_delete_by_service_id(this->coap_service_id);
|
||||
}
|
||||
thread_extension_bbr_old_partition_data_clean(interface_id);
|
||||
thread_bbr_commercial_old_partition_data_clean(interface_id);
|
||||
}
|
||||
#endif // HAVE_THREAD_ROUTER
|
||||
|
||||
|
|
|
@ -0,0 +1,801 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Thread commercial mode implementation for CCM bootstrap.
|
||||
*/
|
||||
#include "nsconfig.h"
|
||||
#include <ns_types.h>
|
||||
#include <string.h>
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "ns_trace.h"
|
||||
#include "common_functions.h"
|
||||
#include "coap_service_api.h"
|
||||
#include "thread_meshcop_lib.h"
|
||||
#include "randLIB.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_discovery.h"
|
||||
#include "6LoWPAN/Thread/thread_constants.h"
|
||||
#include "6LoWPAN/Thread/thread_management_server.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
|
||||
|
||||
/*
|
||||
* Thread 1.2 CCM security credentials
|
||||
*/
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
#if 1
|
||||
/* Hardcoded CSR request */
|
||||
static const unsigned char csr_request[215] = {
|
||||
0x30, 0x81, 0xd4, 0x30, 0x7c, 0x02, 0x01, 0x00, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x0c, 0x0f, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||
0x65, 0x31, 0x32, 0x33, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
|
||||
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xb1,
|
||||
0xab, 0xe8, 0xa2, 0xa1, 0xe6, 0x62, 0x5e, 0xae, 0x9e, 0x7e, 0x41, 0xcf, 0x7e, 0x95, 0x58, 0x19,
|
||||
0x51, 0x47, 0xea, 0x0f, 0xe2, 0xf8, 0xc2, 0x1b, 0x61, 0xa5, 0x30, 0x05, 0xc0, 0x91, 0xb6, 0x07,
|
||||
0xc2, 0x43, 0x46, 0xda, 0x75, 0xc0, 0x58, 0xd8, 0x08, 0xa5, 0xbb, 0xdb, 0xdc, 0x0e, 0xf2, 0x05,
|
||||
0x62, 0xfb, 0x28, 0xbb, 0xa7, 0xd2, 0x9e, 0xef, 0x8f, 0xbf, 0xba, 0xcd, 0x51, 0xa5, 0xfd, 0xa0,
|
||||
0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00,
|
||||
0x30, 0x45, 0x02, 0x20, 0x4e, 0xb2, 0x25, 0x82, 0x24, 0xf6, 0xe1, 0x51, 0xd6, 0x0c, 0x19, 0x60,
|
||||
0x88, 0xb8, 0xe2, 0xfd, 0x90, 0xd2, 0xc1, 0x0f, 0xb0, 0x4f, 0x8e, 0x73, 0x13, 0x5c, 0x9f, 0x42,
|
||||
0x09, 0x68, 0xdf, 0x05, 0x02, 0x21, 0x00, 0xc9, 0xc2, 0x63, 0x83, 0x62, 0x24, 0x15, 0x73, 0xf1,
|
||||
0x63, 0xea, 0xe3, 0xd2, 0xf1, 0x50, 0x48, 0x56, 0xdf, 0x6b, 0xcf, 0xc4, 0x31, 0xc4, 0xcf, 0xbc,
|
||||
0x26, 0xe3, 0x5a, 0x74, 0x62, 0x0f, 0x70
|
||||
};
|
||||
#else
|
||||
/* CSR request with CBOR header*/
|
||||
static const unsigned char csr_request[244] = {
|
||||
0x58, 0xf2, 0x30, 0x81, 0xef, 0x30, 0x81, 0x95, 0x02, 0x01, 0x01, 0x30, 0x33, 0x31, 0x1c, 0x30, 0x1a, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x66, 0x79, 0x20, 0x50, 0x72, 0x6f,
|
||||
0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a,
|
||||
0x4f, 0x53, 0x52, 0x41, 0x4d, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
|
||||
0x04, 0xd8, 0x19, 0x64, 0x07, 0xca, 0x38, 0x01, 0x62, 0xfd, 0x7e, 0xe7, 0x07, 0x8d, 0x21, 0x50, 0x0b, 0x9f,
|
||||
0x00, 0x71, 0x26, 0xaa, 0x55, 0x2a, 0x44, 0x9b, 0xe8, 0xfd, 0xfb, 0x0e, 0x8d, 0x41, 0x01, 0xf2, 0x7b, 0x2e,
|
||||
0x7b, 0xe4, 0x4f, 0x35, 0x00, 0x0b, 0x1f, 0xbc, 0x86, 0x57, 0xa1, 0x69, 0x32, 0x49, 0xcf, 0xd7, 0x2f, 0x0b,
|
||||
0xfa, 0x22, 0x44, 0x0b, 0x6f, 0xf4, 0xb5, 0xbd, 0x0f, 0x20, 0xab, 0xa0, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xb5, 0xa2, 0x8b,
|
||||
0xf9, 0xbf, 0x7d, 0x2c, 0x72, 0x3e, 0xf0, 0xad, 0x1e, 0x38, 0x28, 0xc0, 0xa3, 0xe8, 0xd6, 0x70, 0x9a, 0x2a,
|
||||
0xf8, 0x1d, 0x33, 0x9d, 0xbb, 0x6c, 0x4f, 0x7c, 0x81, 0xb6, 0x71, 0x02, 0x21, 0x00, 0xba, 0x74, 0x50, 0xad,
|
||||
0x27, 0x2e, 0x00, 0x71, 0x68, 0x7f, 0xe0, 0x2c, 0x8c, 0x1b, 0x6f, 0x95, 0x8c, 0x58, 0x1e, 0xe7, 0xe3, 0xa5,
|
||||
0x50, 0xca, 0x12, 0x0a, 0x60, 0x56, 0xd2, 0x3a, 0xe2, 0xeb
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private key for certificate m_device_nxp_sn_and_8021ar.cert.pem -> test registrar will return this as default
|
||||
*/
|
||||
static const unsigned char domain_private_key[138] = {
|
||||
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
|
||||
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02,
|
||||
0x01, 0x01, 0x04, 0x20, 0x49, 0x9c, 0x76, 0x67, 0xd9, 0xae, 0x4e, 0xb6, 0x38, 0xb7, 0xce, 0x25,
|
||||
0x2b, 0x21, 0xf4, 0x6a, 0x88, 0x28, 0xaa, 0x16, 0x74, 0x6e, 0xc3, 0xbc, 0xbb, 0x37, 0x50, 0xc9,
|
||||
0x87, 0xbd, 0xff, 0xbf, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x50, 0xe9, 0x5f, 0xd3, 0xb1, 0x72,
|
||||
0x74, 0xb6, 0xaf, 0x15, 0xae, 0xd7, 0x6d, 0xf9, 0x7f, 0xfa, 0x4f, 0xaf, 0xd6, 0x1f, 0x09, 0x29,
|
||||
0x37, 0xf8, 0x1d, 0x27, 0xeb, 0x31, 0x41, 0x62, 0x52, 0x4e, 0x6b, 0x51, 0x8e, 0x08, 0x72, 0xce,
|
||||
0xc2, 0x43, 0x69, 0x0a, 0x57, 0xb5, 0x54, 0xeb, 0x9b, 0x06, 0xad, 0xed, 0x7c, 0x56, 0x6e, 0x0c,
|
||||
0x23, 0xcb, 0x1e, 0x51, 0x78, 0xe4, 0xae, 0x41, 0x58, 0x15
|
||||
};
|
||||
|
||||
const uint8_t meshcop_nmkp_resp_ignore[] = {
|
||||
MESHCOP_TLV_COMM_SIGNATURE,
|
||||
MESHCOP_TLV_COMM_TOKEN,
|
||||
MESHCOP_TLV_COMMISSIONER_SESSION_ID,
|
||||
MESHCOP_TLV_COMMISSIONER_ID,
|
||||
MESHCOP_TLV_STATE
|
||||
};
|
||||
|
||||
static NS_LIST_DEFINE(ccm_instance_list, thread_ccm_credentials_t, link);
|
||||
|
||||
#define TRACE_GROUP "ccmb"
|
||||
|
||||
static int stringlen(const char *s, int n)
|
||||
{
|
||||
char *end = memchr(s, 0, n);
|
||||
return end ? end - s : n;
|
||||
}
|
||||
|
||||
static int8_t thread_ccm_find_id_by_service(int8_t service_id)
|
||||
{
|
||||
ns_list_foreach(thread_ccm_credentials_t, cur, &ccm_instance_list) {
|
||||
if (cur->coap_service_secure_session_id == service_id) {
|
||||
return cur->interface_id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static thread_ccm_credentials_t *thread_ccm_find_by_service(int8_t service_id)
|
||||
{
|
||||
ns_list_foreach(thread_ccm_credentials_t, cur, &ccm_instance_list) {
|
||||
if (cur->coap_service_secure_session_id == service_id) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void thread_ccm_attach_cb(void *arg)
|
||||
{
|
||||
thread_ccm_credentials_t *this = arg;
|
||||
tr_debug("Attach to new network");
|
||||
if (!this) {
|
||||
return;
|
||||
}
|
||||
if (this->reattach_ongoing) {
|
||||
this->reattach_ongoing = false;
|
||||
thread_nvm_store_mleid_rloc_map_remove();
|
||||
thread_nvm_store_link_info_clear();
|
||||
thread_joiner_application_link_configuration_delete(this->interface_id);
|
||||
thread_bootstrap_connection_error(this->interface_id, CON_ERROR_NETWORK_KICK, NULL);
|
||||
} else {
|
||||
// Cleaning up the joining information
|
||||
if (this->ccm_done_cb) {// This is successfull
|
||||
this->ccm_done_cb(this->interface_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int8_t thread_ccm_network_reattach(int8_t service_id, uint16_t timeout, bool clear_data)
|
||||
{
|
||||
thread_ccm_credentials_t *this = thread_ccm_find_by_service(service_id);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->reattach_ongoing = clear_data;
|
||||
|
||||
// re-attach in any case and close the secure connection
|
||||
this->attach_timeout = eventOS_timeout_ms(thread_ccm_attach_cb, timeout, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_ccm_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len)
|
||||
{
|
||||
/* Certificates used, pskd not needed */
|
||||
(void) service_id;
|
||||
(void) address;
|
||||
(void) port;
|
||||
(void) pw;
|
||||
(void) pw_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_ccm_enroll_parse(protocol_interface_info_entry_t *cur, uint8_t *payload_ptr, uint16_t payload_len)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
uint16_t len, flen;
|
||||
|
||||
ptr = payload_ptr;
|
||||
len = payload_len;
|
||||
// CBOR format check
|
||||
if (*ptr == 0x58) {
|
||||
flen = *(ptr + 1);
|
||||
ptr += 2;
|
||||
len -= 2;
|
||||
} else if (*ptr == 0x59) {
|
||||
flen = common_read_16_bit(ptr + 1);
|
||||
ptr += 3;
|
||||
len -= 3;
|
||||
} else {
|
||||
// no shorter than 23 byte certificates supported
|
||||
flen = 0;
|
||||
}
|
||||
|
||||
if (flen != len ||
|
||||
0 > thread_ccm_network_certificate_set(cur, ptr, len)) {
|
||||
tr_warn("ae response parse failed, len %d != %d", len, flen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_ccm_simple_enroll_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
|
||||
// re-attach in any case and close the secure connection
|
||||
thread_ccm_network_reattach(service_id, 1000, false);
|
||||
coap_service_close_secure_connection(service_id, source_address, source_port);
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_ccm_find_id_by_service(service_id));
|
||||
|
||||
tr_debug("Simple enrollment received len:%d - %s", response_ptr->payload_len, trace_array(response_ptr->payload_ptr, response_ptr->payload_len));
|
||||
|
||||
if (!cur || !cur->thread_info || !response_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread_ccm_enroll_parse(cur, response_ptr->payload_ptr, response_ptr->payload_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_ccm_csrattrs_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) response_ptr;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_ccm_find_id_by_service(service_id));
|
||||
|
||||
if (!cur || !cur->thread_info) {
|
||||
return -1;
|
||||
}
|
||||
tr_info("Receiving csrattrs response sending simpleenroll");
|
||||
|
||||
// TODO Create CSR and private key here... Now we use hardcoded stuff.
|
||||
thread_ccm_network_private_key_set(cur, domain_private_key, sizeof(domain_private_key));
|
||||
|
||||
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, source_address, source_port,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_SIMPLEENROLL, THREAD_CONTENT_FORMAT_PKCS10,
|
||||
csr_request, sizeof(csr_request), thread_ccm_simple_enroll_response_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *thread_ccm_parse_rat_response(uint8_t *data, uint16_t len)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (ptr = (char *)data; (ptr - (char *)data) < len; ptr++) {
|
||||
if (*ptr == 'd') {
|
||||
if (!strncmp(ptr, "domainCAcert", 12)) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int thread_ccm_rat_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
char *ca_cert_ptr = NULL;
|
||||
uint16_t ca_cert_len = 0;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_ccm_find_id_by_service(service_id));
|
||||
|
||||
if (!cur || !cur->thread_info) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_info("Receiving RAT response sending csrattrs request");
|
||||
|
||||
if (!response_ptr || !response_ptr->payload_ptr) {
|
||||
tr_error("No response payload");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Parse CA certificate from RAT response
|
||||
// Replace with CBOR library, when the time is right
|
||||
// Here we receive private key for the CA certi
|
||||
|
||||
ca_cert_ptr = thread_ccm_parse_rat_response(response_ptr->payload_ptr, response_ptr->payload_len);
|
||||
|
||||
if (ca_cert_ptr) {
|
||||
ca_cert_ptr += 13; // Jump over "domainCAcert and some cbor format byte...
|
||||
ca_cert_len = common_read_16_bit((uint8_t *)ca_cert_ptr); // read length
|
||||
ca_cert_ptr += 2;
|
||||
tr_debug("CA cert len %d", ca_cert_len);
|
||||
/* Set domain CA certificate pointer and length */
|
||||
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr);
|
||||
}
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr = ns_dyn_mem_alloc(ca_cert_len);
|
||||
if (!thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr, ca_cert_ptr, ca_cert_len);
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_len = ca_cert_len;
|
||||
} else {
|
||||
tr_error("Response parse failed");
|
||||
}
|
||||
|
||||
// TODO Verify nonce
|
||||
|
||||
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, source_address, source_port,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_GET, THREAD_URI_CSRATTRS, THREAD_CONTENT_FORMAT_CSRATTRS, NULL, 0, thread_ccm_csrattrs_response_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*A2 # map(2)
|
||||
67 # text(7)
|
||||
76657273696F6E # "version"
|
||||
61 # text(1)
|
||||
31 # "1"
|
||||
65 # text(5)
|
||||
6E6F6E6365 # "nonce"
|
||||
48 # bytes(8)
|
||||
13ADD904605D973E # "\x13\xAD\xD9\x04`]\x97>"
|
||||
*
|
||||
*/
|
||||
static int thread_ccm_rat_request_build(uint8_t *rat_payload, int length)
|
||||
{
|
||||
uint8_t *ptr = rat_payload;
|
||||
|
||||
if (length < 30) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*rat_payload++ = 0xa2; // map (2)
|
||||
|
||||
// text (7) "version" + unsigned (1) "1"
|
||||
*rat_payload++ = 0x67;
|
||||
memcpy(rat_payload, "version", 7);
|
||||
rat_payload += 7;
|
||||
*rat_payload++ = 0x61;
|
||||
*rat_payload++ = 0x31;
|
||||
|
||||
// text (5) "nonce" + bytes (8) random nonce
|
||||
// todo: save nonce to verify response against reply.
|
||||
*rat_payload++ = 0x65;
|
||||
memcpy(rat_payload, "nonce", 5);
|
||||
rat_payload += 5;
|
||||
|
||||
*rat_payload++ = 0x48;
|
||||
common_write_64_bit(randLIB_get_64bit(), rat_payload);
|
||||
rat_payload += 8;
|
||||
|
||||
return rat_payload - ptr;
|
||||
}
|
||||
|
||||
static int thread_ccm_ae_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t port, thread_commission_done_cb *done_cb)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
uint8_t rat_payload[30];
|
||||
int rat_len;
|
||||
|
||||
if (!done_cb || !cur) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id = coap_service_initialize(interface_id, port, COAP_SERVICE_OPTIONS_EPHEMERAL_PORT | COAP_SERVICE_OPTIONS_SECURE | 0x80, thread_ccm_security_start_cb, joiner_application_security_done_cb);
|
||||
|
||||
if (0 > coap_service_certificate_set(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, cur->thread_info->ccm_credentials_ptr->device_certificate_ptr, cur->thread_info->ccm_credentials_ptr->device_certificate_len,
|
||||
cur->thread_info->ccm_credentials_ptr->device_pk_ptr, cur->thread_info->ccm_credentials_ptr->device_pk_len)) {
|
||||
tr_debug("coap service certificate set failed");
|
||||
return -1;
|
||||
}
|
||||
tr_debug("start ae commissioning: interface %d, parent: %s, port %d", interface_id, trace_ipv6(parent_address), port);
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->ccm_done_cb = done_cb;
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->ccm_addr, parent_address, 16);
|
||||
thread_info(cur)->ccm_credentials_ptr->ccm_port = port;
|
||||
|
||||
rat_len = thread_ccm_rat_request_build(rat_payload, sizeof(rat_payload));
|
||||
if (rat_len == 0) {
|
||||
tr_debug("RAT request payload build failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// todo: This might not be needed if no extra certificate processing made by device and should directly call simpleenroll
|
||||
coap_service_request_send(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, parent_address, port,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_RAT, THREAD_CONTENT_FORMAT_AUDITNONCE, rat_payload, rat_len, thread_ccm_rat_response_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_ccm_nmkp_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
tr_debug("nmkp provisioning done");
|
||||
|
||||
// re-attach in any case and close the secure connection
|
||||
thread_ccm_network_reattach(service_id, 1000, false);
|
||||
coap_service_close_secure_connection(service_id, source_address, source_port);
|
||||
|
||||
// CoAP message failed - try to reattach
|
||||
if (!response_ptr || !response_ptr->payload_ptr) {
|
||||
tr_debug("nmkp provisioning failed - no response");
|
||||
return -1;
|
||||
}
|
||||
if (thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MASTER_KEY, NULL) < 16 ||
|
||||
thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_XPANID, NULL) < 8 ||
|
||||
thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_NAME, NULL) == 0 ||
|
||||
thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_CHANNEL, NULL) == 0 ||
|
||||
thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_PANID, NULL) == 0 ||
|
||||
thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_PSKC, NULL) < 16) {
|
||||
// Absolutely minimum we must have is master secret to attach.
|
||||
// If commissioner wants to be connected we must have PSKc,Name,Xpanid
|
||||
// If there is some fields missing we could attach, but timestamp must be set to 0 which will then cause synchronization
|
||||
tr_error("Not include all TLv's %s", trace_array(response_ptr->payload_ptr, response_ptr->payload_len));
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread_joiner_application_active_configuration_update(thread_ccm_find_id_by_service(service_id), response_ptr->payload_ptr, response_ptr->payload_len, meshcop_nmkp_resp_ignore, sizeof(meshcop_nmkp_resp_ignore));
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int thread_ccm_nmkp_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t port, thread_commission_done_cb *done_cb)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!done_cb || !cur) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id = coap_service_initialize(cur->id, port, COAP_SERVICE_OPTIONS_EPHEMERAL_PORT | COAP_SERVICE_OPTIONS_SECURE | 0x80, thread_ccm_security_start_cb, NULL);
|
||||
|
||||
if (cur->thread_info->ccm_credentials_ptr) {
|
||||
//Use certificate if set otherwise use PSKd
|
||||
if (0 > coap_service_certificate_set(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, cur->thread_info->ccm_credentials_ptr->domain_certificate_ptr, cur->thread_info->ccm_credentials_ptr->domain_certificate_len,
|
||||
cur->thread_info->ccm_credentials_ptr->domain_pk_ptr, cur->thread_info->ccm_credentials_ptr->domain_pk_len)) {
|
||||
tr_debug("coap service certificate set failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tr_debug("start nmkp commissioning: interface %d, parent: %s, port %d", interface_id, trace_ipv6(parent_address), port);
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->ccm_done_cb = done_cb;
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->ccm_addr, parent_address, 16);
|
||||
thread_info(cur)->ccm_credentials_ptr->ccm_port = port;
|
||||
|
||||
uint8_t *ptr, *data_ptr;
|
||||
uint16_t length;
|
||||
|
||||
tr_debug("Thread joiner finalisation send");
|
||||
length = thread_joiner_application_device_configuration_length(thread_joiner_application_get_device_config(interface_id));
|
||||
|
||||
data_ptr = ptr = ns_dyn_mem_alloc(length);
|
||||
if (!ptr) {
|
||||
tr_error("Failed to start Commissioning");
|
||||
return -1;
|
||||
}
|
||||
ptr = thread_joiner_application_device_configuration_build(ptr, thread_joiner_application_get_device_config(interface_id));
|
||||
|
||||
coap_service_request_send(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, parent_address, port,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_BBR_NMKP_REQ, COAP_CT_OCTET_STREAM, data_ptr, ptr - data_ptr, thread_ccm_nmkp_response_cb);
|
||||
|
||||
ns_dyn_mem_free(data_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate thread commercial commission mode (CCM) struct
|
||||
*/
|
||||
void thread_ccm_allocate(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (thread_info(cur)->ccm_credentials_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr = ns_dyn_mem_alloc(sizeof(thread_ccm_credentials_t));
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
return;
|
||||
}
|
||||
memset(thread_info(cur)->ccm_credentials_ptr, 0, sizeof(thread_ccm_credentials_t));
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->interface_id = cur->id;
|
||||
|
||||
ns_list_add_to_start(&ccm_instance_list, thread_info(cur)->ccm_credentials_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free thread commercial commission mode (CCM) struct
|
||||
*/
|
||||
|
||||
void thread_ccm_free(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!cur || !thread_info(cur) || !thread_info(cur)->ccm_credentials_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr);
|
||||
}
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr);
|
||||
}
|
||||
ns_list_remove(&ccm_instance_list, thread_info(cur)->ccm_credentials_ptr);
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr);
|
||||
thread_info(cur)->ccm_credentials_ptr = NULL;
|
||||
}
|
||||
|
||||
int thread_ccm_device_certificate_set(protocol_interface_info_entry_t *cur, const unsigned char *device_certificate_ptr, uint16_t device_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
|
||||
{
|
||||
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
thread_ccm_allocate(cur);
|
||||
}
|
||||
|
||||
thread_info(cur)->ccm_credentials_ptr->device_certificate_ptr = device_certificate_ptr;
|
||||
thread_info(cur)->ccm_credentials_ptr->device_certificate_len = device_certificate_len;
|
||||
thread_info(cur)->ccm_credentials_ptr->device_pk_ptr = priv_key_ptr;
|
||||
thread_info(cur)->ccm_credentials_ptr->device_pk_len = priv_key_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool thread_ccm_network_certificate_available(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr || !thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int thread_ccm_network_certificate_set(protocol_interface_info_entry_t *cur, const unsigned char *domain_certificate_ptr, uint16_t domain_certificate_len)
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
thread_ccm_allocate(cur);
|
||||
}
|
||||
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr);
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr = NULL;
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_certificate_len = 0;
|
||||
}
|
||||
|
||||
/* Set domain certificate pointer and length */
|
||||
if (domain_certificate_ptr) {
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr = ns_dyn_mem_alloc(domain_certificate_len + thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_len);
|
||||
if (!thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr);
|
||||
return -1;
|
||||
}
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr, domain_certificate_ptr, domain_certificate_len);
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr) {
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr + domain_certificate_len, thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_ptr, thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_len);
|
||||
}
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_certificate_len = domain_certificate_len + thread_info(cur)->ccm_credentials_ptr->domain_ca_certificate_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_ccm_network_private_key_set(protocol_interface_info_entry_t *cur, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
thread_ccm_allocate(cur);
|
||||
}
|
||||
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr);
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr = NULL;
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_pk_len = 0;
|
||||
}
|
||||
|
||||
if (priv_key_ptr) {
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr = ns_dyn_mem_alloc(priv_key_len);
|
||||
if (!thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr) {
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr);
|
||||
ns_dyn_mem_free(thread_info(cur)->ccm_credentials_ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->domain_pk_ptr, priv_key_ptr, priv_key_len);
|
||||
thread_info(cur)->ccm_credentials_ptr->domain_pk_len = priv_key_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_ccm_thread_name_set(protocol_interface_info_entry_t *cur, char thread_name[16])
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
thread_info(cur)->ccm_credentials_ptr = ns_dyn_mem_alloc(sizeof(thread_ccm_credentials_t));
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
return -1;
|
||||
}
|
||||
memset(thread_info(cur)->ccm_credentials_ptr, 0, sizeof(thread_ccm_credentials_t));
|
||||
}
|
||||
memset(thread_info(cur)->ccm_credentials_ptr->domain_name, 0, 16);
|
||||
memcpy(thread_info(cur)->ccm_credentials_ptr->domain_name, thread_name, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_ccm_commission_start(protocol_interface_info_entry_t *cur, uint8_t parent_address[16], discovery_response_list_t *nwk_info, thread_commission_done_cb *done_cb)
|
||||
{
|
||||
|
||||
if (thread_info(cur)->version >= THREAD_VERSION_1_2 && thread_info(cur)->ccm_credentials_ptr) {
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr && nwk_info->ccm_info.nmk_port) {
|
||||
return thread_ccm_nmkp_commission_start(cur->id, parent_address, nwk_info->ccm_info.nmk_port, done_cb);
|
||||
} else if (thread_info(cur)->ccm_credentials_ptr->device_certificate_ptr && nwk_info->ccm_info.ae_port) {
|
||||
return thread_ccm_ae_commission_start(cur->id, parent_address, nwk_info->ccm_info.ae_port, done_cb);
|
||||
} else if (nwk_info->joiner_port) {
|
||||
return thread_joiner_application_pskd_commission_start(cur->id, parent_address, nwk_info->joiner_port, nwk_info->pan_id, nwk_info->extented_pan_id, nwk_info->channel, done_cb);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
discovery_response_list_t *thread_ccm_network_select(protocol_interface_info_entry_t *cur, thread_nwk_discovery_response_list_t *discover_response)
|
||||
{
|
||||
discovery_response_list_t *discovered_network_ptr = NULL;
|
||||
|
||||
if (thread_info(cur)->version >= THREAD_VERSION_1_2 && thread_info(cur)->ccm_credentials_ptr) {
|
||||
/* If we have domain certificate, search for domain to join */
|
||||
if (thread_info(cur)->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) {
|
||||
if ((stringlen((const char *) cur_class->ccm_info.domain_name, 16)) &&
|
||||
(!memcmp(cur_class->ccm_info.domain_name, thread_info(cur)->ccm_credentials_ptr->domain_name, stringlen((const char *) cur_class->ccm_info.domain_name, 16)))) {
|
||||
discovered_network_ptr = cur_class;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No domain, use device certificate*/
|
||||
if (!discovered_network_ptr) {
|
||||
ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) {
|
||||
if (cur_class->ccm_info.ccm_supported) {
|
||||
discovered_network_ptr = cur_class;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return discovered_network_ptr;
|
||||
}
|
||||
|
||||
uint8_t thread_ccm_thread_name_length_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stringlen((const char *)thread_info(cur)->ccm_credentials_ptr->domain_name, 16);
|
||||
}
|
||||
|
||||
uint8_t *thread_ccm_thread_name_ptr_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return thread_info(cur)->ccm_credentials_ptr->domain_name;
|
||||
}
|
||||
|
||||
int thread_ccm_network_certificate_enable(protocol_interface_info_entry_t *cur, int8_t coap_service_id)
|
||||
{
|
||||
// SET certificates
|
||||
if (cur->thread_info->ccm_credentials_ptr && cur->thread_info->ccm_credentials_ptr->domain_certificate_ptr) {
|
||||
if (0 > coap_service_certificate_set(coap_service_id, cur->thread_info->ccm_credentials_ptr->domain_certificate_ptr, cur->thread_info->ccm_credentials_ptr->domain_certificate_len,
|
||||
cur->thread_info->ccm_credentials_ptr->domain_pk_ptr, cur->thread_info->ccm_credentials_ptr->domain_pk_len)) {
|
||||
tr_debug("pBBR certificate set failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int thread_ccm_reenroll_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) service_id;
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_ccm_find_id_by_service(service_id));
|
||||
|
||||
// Close secure connection
|
||||
coap_service_close_secure_connection(service_id, source_address, source_port);
|
||||
|
||||
if (!response_ptr || !cur) {
|
||||
tr_debug("re-enroll failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("re-enroll resp len %d", response_ptr->payload_len);
|
||||
|
||||
// todo:check new certificate
|
||||
// Update certificate
|
||||
if (0 == thread_ccm_enroll_parse(cur, response_ptr->payload_ptr, response_ptr->payload_len)) {
|
||||
// start NMKP with new certificates
|
||||
thread_ccm_network_reattach(service_id, 5000, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int thread_ccm_reenroll_csrattrs_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) service_id;
|
||||
|
||||
if (!response_ptr) {
|
||||
tr_debug("No response to re-enroll csrattr req");
|
||||
return -1;
|
||||
}
|
||||
|
||||
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, source_address, source_port,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_SIMPLEREENROLL, THREAD_CONTENT_FORMAT_PKCS10,
|
||||
csr_request, sizeof(csr_request), thread_ccm_reenroll_resp_cb);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int thread_ccm_reenroll_registrar_addr_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) service_id;
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id));
|
||||
uint8_t *addr_ptr = NULL;
|
||||
|
||||
if (!response_ptr) {
|
||||
tr_debug("No response to registrar addr get");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_REGISTRAR_IPV6_ADDRESS, &addr_ptr)) {
|
||||
tr_debug("Registrar addr get failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("Received registrar address %s", trace_ipv6(addr_ptr));
|
||||
|
||||
//todo: what port?
|
||||
thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id = coap_service_initialize(cur->id, 5684, COAP_SERVICE_OPTIONS_EPHEMERAL_PORT | COAP_SERVICE_OPTIONS_SECURE, thread_ccm_security_start_cb, NULL);
|
||||
|
||||
if (cur->thread_info->ccm_credentials_ptr) {
|
||||
//Use certificate if set otherwise use PSKd
|
||||
if (0 > coap_service_certificate_set(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, cur->thread_info->ccm_credentials_ptr->domain_certificate_ptr, cur->thread_info->ccm_credentials_ptr->domain_certificate_len,
|
||||
cur->thread_info->ccm_credentials_ptr->domain_pk_ptr, cur->thread_info->ccm_credentials_ptr->domain_pk_len)) {
|
||||
tr_debug("coap service certificate set failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
coap_service_request_send(thread_info(cur)->ccm_credentials_ptr->coap_service_secure_session_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, addr_ptr, THREAD_DEFAULT_REGISTRAR_PORT, // TBD: get port from somewhere
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_GET, THREAD_URI_CSRATTRS, THREAD_CONTENT_FORMAT_CSRATTRS, NULL, 0, thread_ccm_reenroll_csrattrs_resp_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_ccm_reenrollment_start(protocol_interface_info_entry_t *cur, int8_t service_id, uint8_t *pbbr_addr)
|
||||
{
|
||||
(void) cur;
|
||||
uint8_t get_tlv[3] = {0};
|
||||
uint8_t *ptr = get_tlv;
|
||||
uint8_t type = MESHCOP_TLV_REGISTRAR_IPV6_ADDRESS;
|
||||
|
||||
//Payload = get tlv including registrar IPV6 address TLV (68)
|
||||
ptr = thread_meshcop_tlv_data_write(get_tlv, MESHCOP_TLV_GET, 1, &type);
|
||||
|
||||
// Send MGMT_BBR_GET.req message to the Primary BBR, requesting the Registrar IPv6 Address TLV
|
||||
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, pbbr_addr, THREAD_MANAGEMENT_PORT, COAP_MSG_TYPE_CONFIRMABLE,
|
||||
COAP_MSG_CODE_REQUEST_GET, THREAD_URI_BBR_DATA_REQ, COAP_CT_NONE, get_tlv, ptr - get_tlv, thread_ccm_reenroll_registrar_addr_resp_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_THREAD_V2 */
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_CCM_H_
|
||||
#define THREAD_CCM_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
void thread_ccm_free(protocol_interface_info_entry_t *cur);
|
||||
|
||||
int thread_ccm_device_certificate_set(protocol_interface_info_entry_t *cur, const unsigned char *device_certificate_ptr, uint16_t device_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len);
|
||||
|
||||
int thread_ccm_network_certificate_set(protocol_interface_info_entry_t *cur, const unsigned char *domain_certificate_ptr, uint16_t domain_certificate_len);
|
||||
|
||||
int thread_ccm_network_private_key_set(protocol_interface_info_entry_t *cur, const unsigned char *priv_key_ptr, uint16_t priv_key_len);
|
||||
|
||||
bool thread_ccm_network_certificate_available(protocol_interface_info_entry_t *cur);
|
||||
|
||||
int thread_ccm_thread_name_set(protocol_interface_info_entry_t *cur, char thread_name[16]);
|
||||
|
||||
int thread_ccm_commission_start(protocol_interface_info_entry_t *cur, uint8_t parent_address[16], discovery_response_list_t *nwk_info, thread_commission_done_cb *done_cb);
|
||||
|
||||
discovery_response_list_t *thread_ccm_network_select(protocol_interface_info_entry_t *cur, thread_nwk_discovery_response_list_t *discover_response);
|
||||
|
||||
uint8_t thread_ccm_thread_name_length_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint8_t *thread_ccm_thread_name_ptr_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
int thread_ccm_network_certificate_enable(protocol_interface_info_entry_t *cur, int8_t coap_service_id);
|
||||
|
||||
int thread_ccm_reenrollment_start(protocol_interface_info_entry_t *cur, int8_t service_id, uint8_t *pbbr_addr);
|
||||
|
||||
#else
|
||||
#define thread_ccm_free(cur);
|
||||
#define thread_ccm_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_ccm_network_certificate_set(cur, domain_certificate_ptr, domain_certificate_len) (-1)
|
||||
#define thread_ccm_network_private_key_set(cur, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_ccm_network_certificate_available(cur) (false)
|
||||
#define thread_ccm_thread_name_set(cur, thread_name) (-1)
|
||||
#define thread_ccm_commission_start(cur, parent_address, port, done_cb) (-1)
|
||||
#define thread_ccm_network_select(cur, discovery_response) (NULL)
|
||||
#define thread_ccm_thread_name_length_get(cur) (0)
|
||||
#define thread_ccm_thread_name_ptr_get(cur) (NULL)
|
||||
#define thread_ccm_network_certificate_enable(cur, coap_service_id) (NULL)
|
||||
#define thread_ccm_reenrollment_start(cur, service_id, pbbr_addr) (-1)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* THREAD_CCM_H_ */
|
|
@ -45,7 +45,7 @@
|
|||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_beacon.h"
|
||||
#include "6LoWPAN/Thread/thread_diagnostic.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "6LoWPAN/Thread/thread_leader_service.h"
|
||||
#include "6LoWPAN/Thread/thread_routing.h"
|
||||
#include "DHCPv6_client/dhcpv6_client_api.h"
|
||||
|
@ -53,7 +53,6 @@
|
|||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_lowpower_private_api.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_border_router_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_nd.h"
|
||||
|
@ -64,9 +63,7 @@
|
|||
#include "6LoWPAN/Thread/thread_management_server.h"
|
||||
#include "6LoWPAN/Thread/thread_resolution_server.h"
|
||||
#include "6LoWPAN/Thread/thread_resolution_client.h"
|
||||
#include "6LoWPAN/Thread/thread_address_registration_client.h"
|
||||
#include "6LoWPAN/Thread/thread_resolution_client.h"
|
||||
#include <6LoWPAN/Thread/thread_extension_bootstrap.h>
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "Service_Libs/mle_service/mle_service_security.h"
|
||||
|
@ -491,7 +488,7 @@ int thread_info_allocate_and_init(protocol_interface_info_entry_t *cur)
|
|||
thread_network_local_server_data_base_init(&cur->thread_info->localServerDataBase);
|
||||
memset(&cur->thread_info->registered_commissioner, 0, sizeof(thread_commissioner_t));
|
||||
thread_dynamic_reed_initialize(&cur->thread_info->routerSelectParameters);
|
||||
thread_extension_allocate(cur);
|
||||
thread_common_ccm_allocate(cur);
|
||||
ns_list_init(&cur->thread_info->childIdReqPending);
|
||||
ns_list_init(&cur->thread_info->child_mcast_list);
|
||||
if (!thread_leader_data_get(cur->thread_info)) {
|
||||
|
@ -530,8 +527,8 @@ void thread_info_deallocate(protocol_interface_info_entry_t *cur)
|
|||
thread_leader_service_leader_data_free(cur->thread_info);
|
||||
thread_data_base_init(cur->thread_info, cur->id);
|
||||
thread_routing_free(&cur->thread_info->routing);
|
||||
thread_extension_free(cur);
|
||||
thread_extension_bootstrap_free(cur);
|
||||
thread_common_ccm_free(cur);
|
||||
thread_ccm_free(cur);
|
||||
if (cur->thread_info->thread_endnode_parent) {
|
||||
ns_dyn_mem_free(cur->thread_info->thread_endnode_parent);
|
||||
cur->thread_info->thread_endnode_parent = NULL;
|
||||
|
@ -988,7 +985,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
|
|||
thread_resolution_client_timer(cur->id, ticks);
|
||||
thread_key_switch_timer(cur, ticks);
|
||||
thread_child_update_req_timer(cur, ticks);
|
||||
thread_address_registration_timer(cur, ticks);
|
||||
thread_bootstrap_address_registration_timer(cur, ticks);
|
||||
|
||||
if (thread_attach_ready(cur) != 0) {
|
||||
return;
|
||||
|
@ -2054,7 +2051,7 @@ static void thread_address_notification_cb(struct protocol_interface_info_entry
|
|||
} else {
|
||||
if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
|
||||
/* Send address notification (our parent doesn't do that for us) */
|
||||
thread_extension_address_registration(interface, addr->address, NULL, false, false);
|
||||
thread_bootstrap_address_registration(interface, addr->address, NULL, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2102,7 +2099,7 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface,
|
|||
}
|
||||
} else {
|
||||
if (addr_added) {
|
||||
thread_address_registration_timer_set(interface, 0, 1);
|
||||
thread_bootstrap_address_registration_timer_set(interface, 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2162,5 +2159,118 @@ void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur)
|
|||
thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL + randLIB_get_random_in_range(0, THREAD_MAINTENANCE_TIMER_INTERVAL / 10);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
void thread_common_ccm_allocate(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
cur->thread_info->ccm_info = ns_dyn_mem_alloc(sizeof(thread_ccm_info_t));
|
||||
if (!cur->thread_info->ccm_info) {
|
||||
return;
|
||||
}
|
||||
memset(cur->thread_info->ccm_info, 0, sizeof(thread_ccm_info_t));
|
||||
cur->thread_info->ccm_info->update_needed = true;
|
||||
cur->thread_info->ccm_info->listen_socket_ae = -1;
|
||||
cur->thread_info->ccm_info->listen_socket_nmkp = -1;
|
||||
|
||||
}
|
||||
|
||||
void thread_common_ccm_free(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
ns_dyn_mem_free(cur->thread_info->ccm_info);
|
||||
cur->thread_info->ccm_info = NULL;
|
||||
}
|
||||
|
||||
bool thread_common_ccm_enabled(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (thread_info(cur)->version <= THREAD_PROTOCOL_VERSION) {
|
||||
// Thread 1.1 version devices dont check the extension
|
||||
return false;
|
||||
}
|
||||
uint16_t securityPolicy = thread_joiner_application_security_policy_get(cur->id);
|
||||
|
||||
if (!(securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t *thread_common_server_tlv_list_get(uint8_t *service_tlv_ptr, uint16_t service_tlv_len, uint16_t *server_tlv_list_len)
|
||||
{
|
||||
uint16_t tlv_length = 0;
|
||||
uint8_t service_id_len = 0;
|
||||
|
||||
if (!(*service_tlv_ptr & 0x80)) {
|
||||
tlv_length += 4;
|
||||
service_tlv_ptr += 4;
|
||||
} else {
|
||||
tlv_length += 1;
|
||||
service_tlv_ptr++;
|
||||
}
|
||||
service_id_len = *service_tlv_ptr++;
|
||||
tlv_length++;
|
||||
|
||||
tlv_length += service_id_len;
|
||||
service_tlv_ptr += service_id_len;
|
||||
|
||||
if (tlv_length > service_tlv_len) {
|
||||
return NULL;
|
||||
}
|
||||
if (server_tlv_list_len) {
|
||||
*server_tlv_list_len = service_tlv_len - tlv_length;
|
||||
}
|
||||
|
||||
return service_tlv_ptr;
|
||||
|
||||
}
|
||||
|
||||
int thread_common_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *mlr_timer_ptr, uint32_t *delay_timer_ptr)
|
||||
{
|
||||
uint8_t *service_tlv_ptr = NULL;
|
||||
uint16_t service_tlv_len;
|
||||
//tr_debug("Search for Primary BBR info");
|
||||
|
||||
do {
|
||||
service_tlv_len = thread_meshcop_tlv_find_next(cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len, THREAD_NWK_DATA_TYPE_SERVICE_DATA | THREAD_NWK_STABLE_DATA, &service_tlv_ptr);
|
||||
if (service_tlv_len > 3 &&
|
||||
(service_tlv_ptr[0] & 0x80) && // THREAD_ENTERPRISE_NUMBER
|
||||
service_tlv_ptr[1] == 1 && // length 1
|
||||
service_tlv_ptr[2] == THREAD_SERVICE_DATA_BBR) {
|
||||
//tr_info("BBR service TLV: %s\r\n", trace_array(service_tlv_ptr, service_tlv_len));
|
||||
// try to parse SUB-TLVs
|
||||
// network_data_server_tlv_parse(service_tlv_ptr, tlv_length);
|
||||
uint16_t server_tlv_len = 0;
|
||||
uint8_t *server_tlv_ptr = thread_common_server_tlv_list_get(service_tlv_ptr, service_tlv_len, &server_tlv_len);
|
||||
uint16_t found_tlv_len;
|
||||
uint8_t *found_tlv = NULL;
|
||||
//tr_info("BBR server TLV: %s\r\n", trace_array(server_tlv_ptr, server_tlv_len));
|
||||
do {
|
||||
found_tlv_len = thread_meshcop_tlv_find_next(server_tlv_ptr, server_tlv_len, THREAD_NWK_DATA_TYPE_SERVER_DATA | THREAD_NWK_STABLE_DATA, &found_tlv);
|
||||
if (found_tlv && found_tlv_len > 8) {
|
||||
//tr_info("BBR server TLV: %s\r\n", trace_array(found_tlv, found_tlv_len));
|
||||
if (addr_ptr) {
|
||||
thread_addr_write_mesh_local_16(addr_ptr, common_read_16_bit(found_tlv), cur->thread_info);
|
||||
}
|
||||
if (seq_ptr) {
|
||||
*seq_ptr = found_tlv[2];
|
||||
}
|
||||
if (delay_timer_ptr) {
|
||||
*delay_timer_ptr = common_read_16_bit(&found_tlv[3]);
|
||||
}
|
||||
if (mlr_timer_ptr) {
|
||||
*mlr_timer_ptr = common_read_32_bit(&found_tlv[5]);
|
||||
if (*mlr_timer_ptr < THREAD_DEFAULT_MIN_MLR_TIMEOUT) {
|
||||
*mlr_timer_ptr = THREAD_DEFAULT_MIN_MLR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} while (found_tlv_len > 0);
|
||||
}
|
||||
} while (service_tlv_len > 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // HAVE_THREAD_V2
|
||||
#endif
|
||||
|
||||
|
|
|
@ -269,8 +269,46 @@ typedef struct thread_router_select {
|
|||
timeout_t *reedAdvertisementTimeout;
|
||||
} thread_router_select_t;
|
||||
|
||||
struct thread_extension_info;
|
||||
struct thread_extension_credentials;
|
||||
typedef struct thread_ccm_info {
|
||||
int8_t coap_service_id;
|
||||
uint8_t sequence_number;
|
||||
uint32_t delay_timer;
|
||||
uint32_t mlr_timer;
|
||||
timeout_t *reset_timeout;
|
||||
uint16_t rloc;
|
||||
uint16_t relay_port_ae;
|
||||
uint16_t relay_port_nmkp;
|
||||
int8_t listen_socket_ae;
|
||||
int8_t listen_socket_nmkp;
|
||||
bool update_needed: 1;
|
||||
} thread_ccm_info_t;
|
||||
|
||||
typedef void thread_commission_done_cb(int8_t interface_id);
|
||||
|
||||
typedef struct thread_ccm_credentials {
|
||||
uint8_t domain_name[16]; // Thread CCM domain name
|
||||
uint8_t ccm_addr[16]; // CCM destination address
|
||||
const unsigned char *device_certificate_ptr; // Pointer to CCM device certificate for Autonomous Enrollment
|
||||
unsigned char *domain_ca_certificate_ptr; // Pointer to Thread CCM domain CA certificate
|
||||
unsigned char *domain_certificate_ptr; // Pointer to Thread CCM domain certificate
|
||||
unsigned char *domain_pk_ptr; // Pointer to Thread domain certificate private key
|
||||
const unsigned char *device_pk_ptr; // Pointer to CCM device certificate private key
|
||||
thread_commission_done_cb *ccm_done_cb;
|
||||
timeout_t *attach_timeout;
|
||||
|
||||
uint16_t device_certificate_len; // Device certificate length
|
||||
uint16_t domain_certificate_len; // Domain certificate length
|
||||
uint16_t domain_ca_certificate_len; // Domain CA certificate length
|
||||
uint16_t device_pk_len; // Device certificate private key length
|
||||
uint16_t domain_pk_len; // Domain certificate private key length
|
||||
uint16_t ccm_port; // CCM destination port
|
||||
|
||||
int8_t coap_service_secure_session_id;
|
||||
int8_t interface_id;
|
||||
bool reattach_ongoing;
|
||||
|
||||
ns_list_link_t link;
|
||||
} thread_ccm_credentials_t;
|
||||
|
||||
typedef struct thread_previous_partition_info_s {
|
||||
uint32_t partitionId; //partition ID of the previous partition
|
||||
|
@ -298,8 +336,8 @@ typedef struct thread_info_s {
|
|||
thread_commissioning_native_select_cb *native_commissioner_cb;
|
||||
thread_network_data_tlv_cb *network_data_tlv_cb;
|
||||
thread_announcement_t *announcement_info;
|
||||
struct thread_extension_info *extension_info;
|
||||
struct thread_extension_credentials *extension_credentials_ptr;
|
||||
thread_ccm_info_t *ccm_info;
|
||||
thread_ccm_credentials_t *ccm_credentials_ptr;
|
||||
thread_attach_device_mode_e thread_device_mode;
|
||||
thread_attach_state_e thread_attached_state; //Indicate Thread stack state
|
||||
thread_registered_mcast_addr_list_t child_mcast_list;
|
||||
|
@ -452,6 +490,19 @@ void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_l
|
|||
void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index);
|
||||
bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf);
|
||||
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur);
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
void thread_common_ccm_allocate(protocol_interface_info_entry_t *cur);
|
||||
void thread_common_ccm_free(protocol_interface_info_entry_t *cur);
|
||||
bool thread_common_ccm_enabled(protocol_interface_info_entry_t *cur);
|
||||
int thread_common_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *mlr_timer_ptr, uint32_t *delay_timer_ptr);
|
||||
#else
|
||||
#define thread_common_ccm_allocate(cur)
|
||||
#define thread_common_ccm_free(cur)
|
||||
#define thread_common_ccm_enabled(cur) (false)
|
||||
#define thread_common_primary_bbr_get(cur, addr_ptr, seq_ptr, mlr_timer_ptr, delay_timer_ptr) (0)
|
||||
|
||||
#endif
|
||||
#else // HAVE_THREAD
|
||||
|
||||
NS_DUMMY_DEFINITIONS_OK
|
||||
|
|
|
@ -188,4 +188,90 @@
|
|||
|
||||
#define THREAD_MCAST_ADDR_PER_MSG 4 // One multicast registration message fits 4 addresses by default
|
||||
|
||||
/**
|
||||
* Minimum specified MLR timeout in seconds
|
||||
*/
|
||||
#define THREAD_DEFAULT_MIN_MLR_TIMEOUT 300
|
||||
|
||||
/**
|
||||
* Default Autonomous enrollment port.
|
||||
*/
|
||||
#define THREAD_DEFAULT_AE_PORT 49192
|
||||
|
||||
/**
|
||||
* Default NMK port.
|
||||
*/
|
||||
#define THREAD_DEFAULT_NMKP_PORT 49193
|
||||
|
||||
/**
|
||||
* Default registrar port
|
||||
*/
|
||||
#define THREAD_DEFAULT_REGISTRAR_PORT 5684
|
||||
|
||||
#define THREAD_URI_BBR_MCAST_LISTENER_REPORT "n/mr" //<* 1.2 feature
|
||||
#define THREAD_URI_BBR_DOMAIN_ADDRESS_REGISTRATION "n/dr" //<* 1.2 feature
|
||||
#define THREAD_URI_BBR_DOMAIN_ADDRESS_NOTIFICATION "n/dn" //<* 1.2 feature
|
||||
#define THREAD_URI_BBR_BB_QRY_NTF "b/bq" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_BB_ANS_NTF "b/ba" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_BMLR_NTF "b/bmr" //<* 1.2 feature
|
||||
#define THREAD_URI_BBR_TRI_RX_NTF "c/rxr" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_NMK_RX_NTF "c/rxb" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_TRI_TX_NTF "c/txr" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_NMK_TX_NTF "c/txb" //<* Backbone border router
|
||||
#define THREAD_URI_BBR_NMKP_REQ "c/cjf" //<* Backbone border router
|
||||
#define THREAD_URI_MGMT_SEC_PENDING_SET "c/sp" //<* Secure Dissemination of Pending Operational Dataset
|
||||
|
||||
#define THREAD_URI_REENROLL_REQ "c/re" //<* Device re-enrollment request
|
||||
#define THREAD_URI_RESET_REQ "c/rt" //<* Device reset request - instruct to remove itself from Thread domain
|
||||
#define THREAD_URI_BBR_DATA_REQ "c/bg" //<* BBR data request
|
||||
#define THREAD_URI_BBR_DATA_SET "c/bs" //<* BBR data set
|
||||
|
||||
#define THREAD_URI_TRI_TX_NTF ".well-known/thread/c/txr" //<* Registrar
|
||||
#define THREAD_URI_TRI_RX_NTF ".well-known/thread/c/rxr" //<* Registrar
|
||||
|
||||
#define THREAD_URI_SIMPLEENROLL ".well-known/est/sen" //<* Registrar
|
||||
#define THREAD_URI_CSRATTRS ".well-known/est/att" //<* Registrar
|
||||
#define THREAD_URI_RAT ".well-known/est/rv" //<* Registrar
|
||||
#define THREAD_URI_SIMPLEREENROLL ".well-known/est/sren" //<* Registrar
|
||||
|
||||
/** Thread BBR service id */
|
||||
#define THREAD_SERVICE_DATA_BBR 0x01
|
||||
|
||||
/** Thread 1.2 CoAP content types */
|
||||
#define THREAD_CONTENT_FORMAT_AUDITNONCE (sn_coap_content_format_e)65000
|
||||
#define THREAD_CONTENT_FORMAT_CSRATTRS (sn_coap_content_format_e)65002
|
||||
#define THREAD_CONTENT_FORMAT_PKCS10 (sn_coap_content_format_e)65003
|
||||
|
||||
/**
|
||||
* Thread 1.2 Security policy options. Default for all is '1';
|
||||
*/
|
||||
|
||||
#define THREAD_SECURITY_POLICY_CCM_DISABLED 0x04
|
||||
#define THREAD_SECURITY_POLICY_AE_DISABLED 0x02
|
||||
#define THREAD_SECURITY_POLICY_NMP_DISABLED 0x01
|
||||
#define THREAD_SECURITY_POLICY_NCR_DISABLED 0x40
|
||||
#define THREAD_SECURITY_POLICY_VR_VALUE 0x07
|
||||
|
||||
/**
|
||||
* Thread 1.2 Status TLV in DUA.rsp message.
|
||||
* /
|
||||
0 – Successful registration
|
||||
2 – Registration rejected: Target EID is not a valid DUA; e.g. incorrect Domain Prefix
|
||||
3 – Registration rejected: DUA is already in use by another Device
|
||||
4 – Registration rejected: BBR resource shortage
|
||||
5 – Registration rejected: BBR is not Primary at this moment
|
||||
6 – Registration failure: Reason(s) not further specified
|
||||
*/
|
||||
|
||||
#define THREAD_ST_DUA_SUCCESS 0
|
||||
#define THREAD_ST_DUA_INVALID 2 //Fatal
|
||||
#define THREAD_ST_DUA_DUPLICATE 3 //Fatal
|
||||
#define THREAD_ST_DUA_NO_RESOURCES 4
|
||||
#define THREAD_ST_DUA_BBR_NOT_PRIMARY 5
|
||||
#define THREAD_ST_DUA_GENERAL_FAILURE 6
|
||||
|
||||
|
||||
#define THREAD_VERSION_1_2 3
|
||||
|
||||
|
||||
#endif /* THREAD_CONSTANTS_H_ */
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "Service_Libs/mle_service/mle_service_api.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "MLE/mle_tlv.h"
|
||||
|
@ -419,6 +419,111 @@ static uint16_t thread_discover_tlv_get(uint8_t version, bool dynamic_bit)
|
|||
}
|
||||
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
static uint8_t thread_discovery_ccm_response_len(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
uint8_t length = 0;
|
||||
uint8_t domain_name_len;
|
||||
// AE port
|
||||
if (!cur || !cur->thread_info->ccm_info) {
|
||||
return 0;
|
||||
}
|
||||
if (cur->thread_info->ccm_info->relay_port_ae) {
|
||||
length += 4;
|
||||
}
|
||||
// NMK port
|
||||
if (cur->thread_info->ccm_info->relay_port_nmkp) {
|
||||
length += 4;
|
||||
}
|
||||
/* Thread 1.2 CCM add-ons */
|
||||
if (cur->thread_info->version >= THREAD_VERSION_1_2 && thread_info(cur)->ccm_credentials_ptr) {
|
||||
// Calculate also following optional TLV's:
|
||||
// Thread domain name TLV
|
||||
domain_name_len = thread_ccm_thread_name_length_get(cur);
|
||||
if (domain_name_len) {
|
||||
length += domain_name_len + 2;
|
||||
}
|
||||
// AE steering data
|
||||
// NMKP Steering Data
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static uint8_t *thread_discovery_ccm_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr)
|
||||
{
|
||||
if (!cur || !cur->thread_info->ccm_info) {
|
||||
return ptr;
|
||||
}
|
||||
// AE port
|
||||
if (cur->thread_info->ccm_info->relay_port_ae) {
|
||||
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_AE_PORT, cur->thread_info->ccm_info->relay_port_ae);
|
||||
}
|
||||
// NMK port
|
||||
if (cur->thread_info->ccm_info->relay_port_nmkp) {
|
||||
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_NMKP_PORT, cur->thread_info->ccm_info->relay_port_nmkp);
|
||||
}
|
||||
/* Thread 1.2 CCM add-ons */
|
||||
if (cur->thread_info->version >= THREAD_VERSION_1_2 && thread_info(cur)->ccm_credentials_ptr) {
|
||||
// Thread domain name TLV
|
||||
if (thread_ccm_thread_name_length_get(cur)) {
|
||||
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_DOMAIN_NAME, thread_ccm_thread_name_length_get(cur), thread_ccm_thread_name_ptr_get(cur));
|
||||
}
|
||||
// Build also following optional TLV's, when supported:
|
||||
// AE steering data
|
||||
// NMKP Steering Data
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
void thread_discovery_ccm_response_read(discovery_response_list_t *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len)
|
||||
{
|
||||
uint8_t domain_data_len;
|
||||
uint8_t *domain_data_ptr;
|
||||
|
||||
domain_data_len = thread_meshcop_tlv_find(data_ptr, data_len, MESHCOP_TLV_DOMAIN_NAME, &domain_data_ptr);
|
||||
if (domain_data_len > 16) {
|
||||
domain_data_len = 0;
|
||||
}
|
||||
|
||||
if (domain_data_len) {
|
||||
memcpy(nwk_info->ccm_info.domain_name, domain_data_ptr, domain_data_len);
|
||||
}
|
||||
|
||||
thread_meshcop_tlv_data_get_uint16(data_ptr, data_len, MESHCOP_TLV_AE_PORT, &nwk_info->ccm_info.ae_port);
|
||||
thread_meshcop_tlv_data_get_uint16(data_ptr, data_len, MESHCOP_TLV_NMKP_PORT, &nwk_info->ccm_info.nmk_port);
|
||||
nwk_info->ccm_info.ccm_supported = (discover_response_tlv >> 10) & 1;
|
||||
}
|
||||
|
||||
void thread_discovery_ccm_info_write(uint16_t *data, uint8_t version, uint16_t securityPolicy)
|
||||
{
|
||||
if (version == 3 && !(securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED)) {
|
||||
*data |= (uint16_t)(1 << 10);
|
||||
}
|
||||
}
|
||||
|
||||
bool thread_discovery_ccm_joining_enabled(int8_t interface_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->thread_info->ccm_info) {
|
||||
return false;
|
||||
}
|
||||
if (cur->thread_info->ccm_info->relay_port_ae ||
|
||||
cur->thread_info->ccm_info->relay_port_nmkp) {
|
||||
tr_warn("Commercial joiner router enabled");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
#define thread_discovery_ccm_response_len(cur) (0)
|
||||
#define thread_discovery_ccm_response_write(cur, ptr) (ptr)
|
||||
#define thread_discovery_ccm_response_read(nwk_info, discover_response_tlv, data_ptr, data_len)
|
||||
#define thread_discovery_ccm_info_write(data, version, securityPolicy)
|
||||
#define thread_discovery_ccm_joining_enabled(interface_id) (false)
|
||||
|
||||
#endif
|
||||
|
||||
static int thread_discovery_request_send(thread_discovery_class_t *class, thread_discovery_request_info_t *discovery)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = class->interface;
|
||||
|
@ -504,9 +609,6 @@ static int thread_discovery_announce_request_send(thread_discovery_class_t *clas
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int thread_discovery_response_send(thread_discovery_class_t *class, thread_discovery_response_msg_t *msg_buffers)
|
||||
{
|
||||
link_configuration_s *linkConfiguration = thread_joiner_application_get_config(class->interface_id);
|
||||
|
@ -538,7 +640,7 @@ static int thread_discovery_response_send(thread_discovery_class_t *class, threa
|
|||
message_length += 4;
|
||||
}
|
||||
|
||||
message_length += thread_extension_discover_response_len(cur);
|
||||
message_length += thread_discovery_ccm_response_len(cur);
|
||||
|
||||
uint16_t buf_id = mle_service_msg_allocate(class->interface_id, message_length + 2, false, MLE_COMMAND_DISCOVERY_RESPONSE);
|
||||
if (buf_id == 0) {
|
||||
|
@ -557,7 +659,7 @@ static int thread_discovery_response_send(thread_discovery_class_t *class, threa
|
|||
*ptr++ = message_length;
|
||||
uint16_t discover_response_tlv = thread_discover_tlv_get(class->version, (linkConfiguration->securityPolicy & SECURITY_POLICY_NATIVE_COMMISSIONING_ALLOWED));
|
||||
|
||||
thread_extension_discover_response_tlv_write(&discover_response_tlv, class->version, linkConfiguration->securityPolicy);
|
||||
thread_discovery_ccm_info_write(&discover_response_tlv, class->version, linkConfiguration->securityPolicy);
|
||||
|
||||
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_DISCOVERY_RESPONSE, discover_response_tlv);
|
||||
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_XPANID, 8, linkConfiguration->extented_pan_id);
|
||||
|
@ -575,7 +677,7 @@ static int thread_discovery_response_send(thread_discovery_class_t *class, threa
|
|||
}
|
||||
}
|
||||
|
||||
ptr = thread_extension_discover_response_write(cur, ptr);
|
||||
ptr = thread_discovery_ccm_response_write(cur, ptr);
|
||||
|
||||
if (mle_service_update_length_by_ptr(buf_id, ptr) != 0) {
|
||||
tr_debug("Buffer overflow at message write");
|
||||
|
@ -849,7 +951,7 @@ static void thread_discovery_request_msg_handler(thread_discovery_class_t *disco
|
|||
thread_management_server_data_t joiner_router_info;
|
||||
if (0 != thread_management_server_commisoner_data_get(discovery_class->interface_id, &joiner_router_info) ||
|
||||
!joiner_router_info.joiner_router_enabled) {
|
||||
if (!thread_extension_joining_enabled(discovery_class->interface_id)) {
|
||||
if (!thread_discovery_ccm_joining_enabled(discovery_class->interface_id)) {
|
||||
tr_debug("Drop by Joining disabled");
|
||||
return;
|
||||
}
|
||||
|
@ -982,8 +1084,8 @@ static void thread_discovery_response_msg_handler(thread_discovery_class_t *disc
|
|||
}
|
||||
|
||||
if (discovery_class->discovery_request->joiner_flag && (!joiner_port_valid || steerin_data_length == 0)) {
|
||||
if (thread_extension_version_check(discovery_class->interface->thread_info->version)) {
|
||||
if (!discovery_class->interface->thread_info->extension_credentials_ptr) {
|
||||
if (discovery_class->interface->thread_info->version >= THREAD_VERSION_1_2) {
|
||||
if (!discovery_class->interface->thread_info->ccm_credentials_ptr) {
|
||||
tr_debug("Dropped, no joiner info");
|
||||
}
|
||||
} else {
|
||||
|
@ -1019,7 +1121,7 @@ static void thread_discovery_response_msg_handler(thread_discovery_class_t *disc
|
|||
|
||||
thread_meshcop_tlv_data_get_uint16(discovery_tlv.dataPtr, discovery_tlv.tlvLen, MESHCOP_TLV_COMMISSIONER_UDP_PORT, &nwk_info->commissioner_port);
|
||||
|
||||
thread_extension_discover_response_read(nwk_info, discover_response_tlv, discovery_tlv.dataPtr, discovery_tlv.tlvLen);
|
||||
thread_discovery_ccm_response_read(nwk_info, discover_response_tlv, discovery_tlv.dataPtr, discovery_tlv.tlvLen);
|
||||
|
||||
//Add to last
|
||||
if (discovery_class->discovery_request->native_commisioner_scan) {
|
||||
|
|
|
@ -32,8 +32,16 @@
|
|||
|
||||
struct protocol_interface_info_entry;
|
||||
|
||||
/* Structure that discovery_response_list_t */
|
||||
typedef struct discovery_additional_info {
|
||||
uint8_t domain_name[16];
|
||||
uint16_t ae_port;
|
||||
uint16_t nmk_port;
|
||||
bool ccm_supported: 1;
|
||||
} discovery_additional_info_t;
|
||||
|
||||
typedef struct discovery_response_list {
|
||||
uint8_t reserved_opaque[21];
|
||||
discovery_additional_info_t ccm_info;
|
||||
uint8_t network_name[16];
|
||||
uint8_t steering_data[16];
|
||||
uint8_t extented_pan_id[8];
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Thread extensions for network bootstrap.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_EXTENSION_H_
|
||||
#define THREAD_EXTENSION_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct discovery_response_list;
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
void thread_extension_allocate(protocol_interface_info_entry_t *cur);
|
||||
void thread_extension_free(protocol_interface_info_entry_t *cur);
|
||||
void thread_extension_init(int8_t interface_id, int8_t coap_service_id);
|
||||
void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur);
|
||||
void thread_extension_network_data_process(struct protocol_interface_info_entry *cur);
|
||||
int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr);
|
||||
void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected);
|
||||
void thread_extension_child_address_registration_response_process(struct protocol_interface_info_entry *interface);
|
||||
void thread_extension_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len);
|
||||
void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur);
|
||||
bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16);
|
||||
void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t *interface);
|
||||
void thread_extension_address_registration_trigger(protocol_interface_info_entry_t *interface);
|
||||
bool thread_extension_enabled(protocol_interface_info_entry_t *cur);
|
||||
bool thread_extension_version_check(uint8_t version);
|
||||
void thread_extension_discover_response_read(struct discovery_response_list *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len);
|
||||
void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy);
|
||||
int thread_extension_service_init(protocol_interface_info_entry_t *cur);
|
||||
void thread_extension_addr_ntf_send(struct protocol_interface_info_entry *cur, uint8_t *destination_address, const uint8_t *addr_data_ptr, uint8_t bbr_status);
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
bool thread_extension_joining_enabled(int8_t interface_id);
|
||||
bool thread_extension_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur);
|
||||
uint8_t thread_extension_discover_response_len(protocol_interface_info_entry_t *cur);
|
||||
uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr);
|
||||
|
||||
#else
|
||||
#define thread_extension_joining_enabled(interface_id) (false)
|
||||
#define thread_extension_is_reed_upgrade_allowed(cur) (true)
|
||||
#define thread_extension_discover_response_len(cur) (0)
|
||||
#define thread_extension_discover_response_write(cur, ptr) (ptr)
|
||||
#endif //HAVE_THREAD_ROUTER
|
||||
#else
|
||||
|
||||
#define thread_extension_allocate(cur) ((void) 0)
|
||||
#define thread_extension_free(cur) ((void) 0)
|
||||
#define thread_extension_init(interface_id,coap_service_id) ((void) 0)
|
||||
#define thread_extension_network_data_process(cur) ((void) 0)
|
||||
#define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1)
|
||||
#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) ((void) 0)
|
||||
#define thread_extension_child_address_registration_response_process(interface) ((void) 0)
|
||||
#define thread_extension_aloc_generate(cur) ((void) 0)
|
||||
#define thread_extension_aloc_map(cur, addr16) (false)
|
||||
#define thread_extension_mcast_subscrition_change(interface) ((void) 0)
|
||||
#define thread_extension_enabled(cur) (false)
|
||||
#define thread_extension_is_reed_upgrade_allowed(cur) (true)
|
||||
#define thread_extension_version_check(version) (false)
|
||||
#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) ((void) 0)
|
||||
#define thread_extension_discover_response_tlv_write(data, version, securityPolicy) ((void) 0)
|
||||
#define thread_extension_service_init(cur) ((void) 0)
|
||||
#define thread_extension_joining_enabled(interface_id) (false)
|
||||
#define thread_extension_discover_response_len(cur) (0)
|
||||
#define thread_extension_discover_response_write(cur, ptr) (ptr)
|
||||
#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) ((void) 0)
|
||||
#define thread_extension_dua_address_generate(cur, domain_prefix, domain_prefix_len) ((void) 0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* THREAD_EXTENSION_H_ */
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Thread extension for bbr.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_EXTENSION_BBR_H_
|
||||
#define THREAD_EXTENSION_BBR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Thread PBBR ML-EID map structure
|
||||
*/
|
||||
typedef struct thread_pbbr_dua_info {
|
||||
uint8_t mleid_ptr[8];
|
||||
uint32_t last_contact_time;
|
||||
} thread_pbbr_dua_info_t;
|
||||
|
||||
#if defined(HAVE_THREAD_V2) && defined(HAVE_THREAD_BORDER_ROUTER)
|
||||
int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_id);
|
||||
void thread_extension_bbr_delete(int8_t interface_id);
|
||||
bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc);
|
||||
void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds);
|
||||
int thread_extension_bbr_sequence_number_set(int8_t interface_id, uint8_t seq_number);
|
||||
int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
|
||||
int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port);
|
||||
void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur);
|
||||
int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
|
||||
void thread_extension_bbr_old_partition_data_clean(int8_t interface_id);
|
||||
void thread_extension_bbr_status_override_get(uint8_t *dua_status, uint8_t *dua_count, uint8_t *ba_failure_count);
|
||||
void thread_extension_bbr_status_override_set(uint8_t dua_status, uint8_t dua_count, uint8_t ba_failure_count);
|
||||
void thread_extension_status_override_count_set(uint8_t value);
|
||||
void thread_extension_bbr_mcast_fwd_check(int8_t interface_id, bool *multicast_fwd);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define thread_extension_bbr_init(interface_id, backbone_interface_id)
|
||||
#define thread_extension_bbr_delete(interface_id)
|
||||
#define thread_extension_bbr_nd_query_process(cur, target_addr, rloc) false
|
||||
#define thread_extension_bbr_seconds_timer(interface_id, seconds)
|
||||
#define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay)
|
||||
#define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1)
|
||||
#define thread_extension_bbr_route_update(cur)
|
||||
#define thread_extension_bbr_sequence_number_set(interface_id, seq_number) (-1)
|
||||
#define thread_extension_bbr_prefix_set(interface_id, prefix) 0
|
||||
#define thread_extension_bbr_old_partition_data_clean(interface_id)
|
||||
#define thread_extension_bbr_status_override_get(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_extension_bbr_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
#define thread_extension_status_override_count_set(value)
|
||||
#define thread_extension_bbr_mcast_fwd_check(interface_id, multicast_fwd)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //HAVE_THREAD_BORDER_ROUTER && HAVE_THREAD_V2
|
|
@ -1,56 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef THREAD_EXTENSION_BOOTSTRAP_H_
|
||||
#define THREAD_EXTENSION_BOOTSTRAP_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define thread_extension_bootstrap_free(cur);
|
||||
#define thread_extension_bootstrap_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_extension_bootstrap_network_certificate_set(cur, domain_certificate_ptr, domain_certificate_len) (-1)
|
||||
#define thread_extension_bootstrap_network_certificate_available(cur) (false)
|
||||
#define thread_extension_bootstrap_network_private_key_set(cur, priv_key_ptr, priv_key_len) (-1)
|
||||
#define thread_extension_bootstrap_thread_name_set(cur, thread_name) (-1)
|
||||
#define thread_extension_bootstrap_commission_start(cur, parent_address, port, done_cb) (-1)
|
||||
#define thread_extension_bootstrap_network_select(cur, discovery_response) (NULL)
|
||||
#define thread_extension_bootstrap_thread_name_length_get(cur) (0)
|
||||
#define thread_extension_bootstrap_thread_name_ptr_get(cur) (NULL)
|
||||
#define thread_extension_bootstrap_network_certificate_enable(cur, coap_service_id) (NULL)
|
||||
#define thread_extension_bootstrap_reenrollment_start(cur, service_id, pbbr_addr) (-1)
|
||||
#define thread_extension_bootstrap_network_reattach(interface_id, timeout) (-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* THREAD_EXTENSION_BOOTSTRAP_H_ */
|
|
@ -57,7 +57,6 @@
|
|||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_network_synch.h"
|
||||
#include "6LoWPAN/Thread/thread_lowpower_private_api.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
|
@ -469,10 +468,8 @@ static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *ml
|
|||
static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *cur, thread_scanned_parent_t *scanned_parent, uint16_t version, thread_connectivity_t *connectivity)
|
||||
{
|
||||
(void) connectivity;
|
||||
(void) cur;
|
||||
bool cur_version = thread_extension_version_check(thread_info(cur)->version);
|
||||
|
||||
if (!cur_version) {
|
||||
if (thread_info(cur)->version < THREAD_VERSION_1_2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -623,7 +620,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
|
|||
}
|
||||
}
|
||||
|
||||
if (thread_extension_enabled(cur) &&
|
||||
if (thread_common_ccm_enabled(cur) &&
|
||||
thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER &&
|
||||
leaderData.weighting < thread_info(cur)->partition_weighting) {
|
||||
// Only applies to extensions and only routers that can form new partitions can ignore lower weight
|
||||
|
|
|
@ -58,8 +58,7 @@
|
|||
#include "thread_network_synch.h"
|
||||
#include "thread_network_data_lib.h"
|
||||
#include "thread_joiner_application.h"
|
||||
#include "thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "mac_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "thread_nvm_store.h"
|
||||
|
@ -214,7 +213,7 @@ typedef struct {
|
|||
device_configuration_s *device_configuration_ptr;
|
||||
uint8_t parent_address[16];
|
||||
uint16_t parent_port;
|
||||
thread_joiner_application_commission_done_cb *done_cb;
|
||||
thread_commission_done_cb *done_cb;
|
||||
timeout_t *attach_timeout;
|
||||
timeout_t *entrust_timeout;
|
||||
uint32_t provisioning_timeout;
|
||||
|
@ -741,7 +740,7 @@ static void configuration_set_generate(int8_t interface_id, configuration_set_t
|
|||
response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_NETWORK_NAME, stringlen((char *)&configuration_ptr->name, 16), configuration_ptr->name);
|
||||
*response_ptr++ = MESHCOP_TLV_SECURITY_POLICY; // type
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (thread_extension_version_check(thread_info(cur)->version)) {
|
||||
if (thread_info(cur)->version >= THREAD_VERSION_1_2) {
|
||||
*response_ptr++ = 4; // length
|
||||
response_ptr = common_write_16_bit(configuration_ptr->key_rotation, response_ptr);
|
||||
*response_ptr++ = configuration_ptr->securityPolicy;
|
||||
|
@ -1857,7 +1856,7 @@ static int thread_joiner_application_entrust_recv_cb(int8_t service_id, uint8_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
int thread_joiner_application_pskd_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t joiner_port, uint16_t panid, uint8_t xpanid[8], uint8_t channel, thread_joiner_application_commission_done_cb *done_cb)
|
||||
int thread_joiner_application_pskd_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t joiner_port, uint16_t panid, uint8_t xpanid[8], uint8_t channel, thread_commission_done_cb *done_cb)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
thread_joiner_t *this = thread_joiner_find(interface_id);
|
||||
|
|
|
@ -162,15 +162,6 @@ thread_provisioning_status_e thread_joiner_application_provisioning_get(int8_t i
|
|||
*/
|
||||
int thread_joiner_application_form_network(int8_t interface_id, uint8_t *commissioning_credentials_ptr, char *name_ptr);
|
||||
|
||||
/** Commissioning done callback.
|
||||
*
|
||||
* This callback is called when commissioning is made and new attach can be made with new static configuration.
|
||||
*
|
||||
* /param interface interface id of this thread instance.
|
||||
*
|
||||
*/
|
||||
typedef void thread_joiner_application_commission_done_cb(int8_t interface_id);
|
||||
|
||||
/** Commissioning start.
|
||||
*
|
||||
* Start commissioning process to this network
|
||||
|
@ -178,7 +169,7 @@ typedef void thread_joiner_application_commission_done_cb(int8_t interface_id);
|
|||
* /param interface interface id of this thread instance.
|
||||
*
|
||||
*/
|
||||
int thread_joiner_application_pskd_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t joiner_port, uint16_t panid, uint8_t xpanid[8], uint8_t channel, thread_joiner_application_commission_done_cb *done_cb);
|
||||
int thread_joiner_application_pskd_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t joiner_port, uint16_t panid, uint8_t xpanid[8], uint8_t channel, thread_commission_done_cb *done_cb);
|
||||
|
||||
/** One second ticker for delayed configurations.
|
||||
*
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_management_server.h"
|
||||
#include "6LoWPAN/Thread/thread_commissioning_if.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_leader_service.h"
|
||||
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_network_synch.h"
|
||||
|
|
|
@ -0,0 +1,619 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <ns_types.h>
|
||||
#include <nsdynmemLIB.h>
|
||||
#include "thread_lowpower_api.h"
|
||||
#include <string.h>
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "common_functions.h"
|
||||
|
||||
|
||||
#include "thread_common.h"
|
||||
#include "thread_config.h"
|
||||
#include "eventOS_event_timer.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "thread_lowpower_api.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "thread_management_if.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
#define TRACE_GROUP "lpwr"
|
||||
|
||||
#define METRICS_LEN 18
|
||||
|
||||
typedef struct data_response_s {
|
||||
thread_lowpower_resp_cb *data_response_cb;
|
||||
uint16_t request_wait_timer;
|
||||
uint16_t series_flags;
|
||||
uint8_t probe_count;
|
||||
uint8_t destination_address[16];
|
||||
int8_t interface_id;
|
||||
uint8_t metrics_requested[METRICS_LEN];
|
||||
uint8_t metrics_len;
|
||||
uint8_t series_id;
|
||||
} data_response_t;
|
||||
|
||||
typedef struct data_metrics_s {
|
||||
uint8_t metrics_requested[METRICS_LEN];
|
||||
uint8_t metrics_value[METRICS_LEN];
|
||||
uint8_t req_metrics_len;
|
||||
uint8_t address[16];
|
||||
uint16_t timeout_timer;
|
||||
bool link_metrics_ready: 1;
|
||||
uint16_t query_ID;
|
||||
uint8_t forward_series_id;
|
||||
uint8_t forward_series_flags;
|
||||
ns_list_link_t link;
|
||||
} data_metrics_t;
|
||||
|
||||
static NS_LIST_DEFINE(thread_lowpower_data_metrics_instance_list, data_metrics_t, link);
|
||||
|
||||
static data_response_t data_response;
|
||||
data_response_t *data_response_ptr = &data_response;
|
||||
//Link Metrics Query TLV
|
||||
#define LINK_METRIC_SUB_TLV_LINK_METRIC_REPORT 0
|
||||
#define LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_ID 1
|
||||
#define LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_OPTIONS 2
|
||||
|
||||
// Link Metrics Management TLV
|
||||
#define LINK_METRIC_SUB_TLV_FORWARD_PROBE 3
|
||||
#define LINK_METRIC_SUB_TLV_REVERSE_PROBE 4
|
||||
#define LINK_METRIC_SUB_TLV_STATUS 5
|
||||
#define LINK_METRIC_SUB_TLV_TRACKING_CAPABILITIES 6
|
||||
#define LINK_METRIC_SUB_TLV_ENHANCED_ACK_CONFIGURATION 7
|
||||
|
||||
|
||||
static data_metrics_t *thread_lowpower_data_metrics_find_by_source_address(uint8_t *address)
|
||||
{
|
||||
data_metrics_t *this = NULL;
|
||||
ns_list_foreach(data_metrics_t, cur_ptr, &thread_lowpower_data_metrics_instance_list) {
|
||||
if (memcmp(cur_ptr->address, address, 16) == 0) {
|
||||
this = cur_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static data_metrics_t *thread_lowpower_data_metrics_create(uint8_t *address)
|
||||
{
|
||||
data_metrics_t *this = thread_lowpower_data_metrics_find_by_source_address(address);
|
||||
|
||||
if (!this) {
|
||||
this = ns_dyn_mem_alloc(sizeof(data_metrics_t));
|
||||
}
|
||||
if (!this) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(this->address, address, 16);
|
||||
memset(this->metrics_requested, 0, METRICS_LEN);
|
||||
memset(this->metrics_value, 0, METRICS_LEN);
|
||||
this->req_metrics_len = 0;
|
||||
this->timeout_timer = 0;
|
||||
this->link_metrics_ready = false;
|
||||
this->query_ID = 0;
|
||||
ns_list_add_to_start(&thread_lowpower_data_metrics_instance_list, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
void thread_lowpower_data_metrics_delete(uint8_t *address)
|
||||
{
|
||||
data_metrics_t *this = thread_lowpower_data_metrics_find_by_source_address(address);
|
||||
if (!this) {
|
||||
return;
|
||||
}
|
||||
ns_list_remove(&thread_lowpower_data_metrics_instance_list, this);
|
||||
ns_dyn_mem_free(this);
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t *thread_lowpower_tlv_write_link_metrics_query_id(uint8_t *ptr, uint16_t query_id)
|
||||
{
|
||||
*ptr++ = LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_ID;
|
||||
*ptr++ = 2;
|
||||
ptr = common_write_16_bit(query_id, ptr);
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_link_metrics_query_options(uint8_t *ptr, uint8_t *req_list_ptr, uint8_t req_list_len)
|
||||
{
|
||||
*ptr++ = LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_OPTIONS;
|
||||
*ptr++ = req_list_len;
|
||||
memcpy(ptr, req_list_ptr, req_list_len);
|
||||
ptr += req_list_len;
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_link_metrics_query(uint8_t *ptr, uint8_t *req_list_ptr, uint8_t req_list_len, uint16_t query_id)
|
||||
{
|
||||
*ptr++ = MLE_TYPE_LINK_METRICS_QUERY;
|
||||
if (req_list_len) {
|
||||
*ptr++ = 6 + req_list_len; // query id type + len + query id = 4 bytes, query options type + len + flags = 2 bytes + flags
|
||||
} else {
|
||||
*ptr++ = 4; // query id type + len + query id = 4 bytes
|
||||
}
|
||||
ptr = thread_lowpower_tlv_write_link_metrics_query_id(ptr, query_id);
|
||||
if (req_list_len) {
|
||||
ptr = thread_lowpower_tlv_write_link_metrics_query_options(ptr, req_list_ptr, req_list_len);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_metrics_forward_probe(uint8_t *ptr, uint8_t series_id, uint8_t series_flags, uint16_t timeout, uint8_t *req_list_ptr, uint8_t req_list_len)
|
||||
{
|
||||
*ptr++ = LINK_METRIC_SUB_TLV_FORWARD_PROBE;
|
||||
*ptr++ = 4 + req_list_len; // query id type + len + query id = 4 bytes, query options type + len + flags = 2 bytes + flags
|
||||
*ptr++ = series_id;
|
||||
*ptr++ = series_flags;
|
||||
ptr = common_write_16_bit(timeout, ptr);
|
||||
memcpy(ptr, req_list_ptr, req_list_len);
|
||||
ptr += req_list_len;
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_status(uint8_t *ptr, uint16_t status)
|
||||
{
|
||||
*ptr++ = LINK_METRIC_SUB_TLV_STATUS;
|
||||
*ptr++ = 2;
|
||||
ptr = common_write_16_bit(status, ptr);
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_metrics_management_forward_probe_request(uint8_t *ptr, uint8_t series_id, uint8_t series_flags, uint16_t timeout, uint8_t *req_list_ptr, uint8_t req_list_len)
|
||||
{
|
||||
*ptr++ = MLE_TYPE_LINK_METRICS_MANAGEMENT;
|
||||
*ptr++ = 6 + req_list_len; // query id type + len + query id = 4 bytes, query options type + len + flags = 2 bytes + flags
|
||||
ptr = thread_lowpower_tlv_write_metrics_forward_probe(ptr, series_id, series_flags, timeout, req_list_ptr, req_list_len);
|
||||
return ptr;
|
||||
}
|
||||
static uint8_t *thread_lowpower_tlv_write_metrics_management_status(uint8_t *ptr, uint16_t status)
|
||||
{
|
||||
*ptr++ = MLE_TYPE_LINK_METRICS_MANAGEMENT;
|
||||
*ptr++ = 4;
|
||||
ptr = thread_lowpower_tlv_write_status(ptr, status);
|
||||
return ptr;
|
||||
}
|
||||
static int thread_lowpower_requested_metrics_management_query_save(uint8_t *address, uint8_t *data_ptr, uint16_t data_len)
|
||||
{
|
||||
mle_tlv_info_t query_info;
|
||||
uint8_t *forward_probe_ptr;
|
||||
uint8_t forward_probe_len;
|
||||
data_metrics_t *this;
|
||||
|
||||
if (mle_tlv_option_discover(data_ptr, data_len, MLE_TYPE_LINK_METRICS_MANAGEMENT, &query_info) < 4) {
|
||||
// No query TLV present
|
||||
return 0;
|
||||
}
|
||||
forward_probe_len = thread_tmfcop_tlv_find(query_info.dataPtr, query_info.tlvLen, LINK_METRIC_SUB_TLV_FORWARD_PROBE, &forward_probe_ptr);
|
||||
|
||||
if (forward_probe_len < 5) {
|
||||
// Not present or length not enough
|
||||
return 0;
|
||||
}
|
||||
|
||||
this = thread_lowpower_data_metrics_create(address);
|
||||
|
||||
if (!this) {
|
||||
//query aready exists
|
||||
tr_error("query not created");
|
||||
return -3;
|
||||
}
|
||||
tr_debug("saving link metrics requested");
|
||||
|
||||
this->link_metrics_ready = false;
|
||||
memcpy(this->address, address, 16);
|
||||
this->forward_series_id = *forward_probe_ptr++;
|
||||
this->forward_series_flags = *forward_probe_ptr++;
|
||||
this->timeout_timer = common_read_16_bit(forward_probe_ptr);
|
||||
forward_probe_ptr += 2;
|
||||
this->req_metrics_len = forward_probe_len - 4; // after 4 bytes omes the query types
|
||||
|
||||
// Check that we dont go over maximum query count
|
||||
if (this->req_metrics_len > METRICS_LEN) {
|
||||
this->req_metrics_len = METRICS_LEN;
|
||||
}
|
||||
for (uint8_t i = 0; i < this->req_metrics_len; i++) {
|
||||
//save the read bytes for computing the results
|
||||
this->metrics_requested[i] = *forward_probe_ptr++;
|
||||
}
|
||||
tr_info("Forward probe query made by %s id:%d timeout:%d", trace_ipv6(this->address), this->forward_series_id, this->timeout_timer);
|
||||
return 0;
|
||||
}
|
||||
static int thread_lowpower_requested_single_query_save(uint8_t *address, uint8_t *data_ptr, uint16_t data_len)
|
||||
{
|
||||
mle_tlv_info_t query_info;
|
||||
uint8_t *query_options_ptr;
|
||||
uint8_t query_options_len;
|
||||
data_metrics_t *this = NULL;
|
||||
|
||||
if (!mle_tlv_type_requested(MLE_TYPE_LINK_METRICS_REPORT, data_ptr, data_len)) {
|
||||
//No single link metric requested so cant respond no need to process query
|
||||
return 0;
|
||||
}
|
||||
if (mle_tlv_option_discover(data_ptr, data_len, MLE_TYPE_LINK_METRICS_QUERY, &query_info) < 6) {
|
||||
return 0;
|
||||
}
|
||||
tr_debug("Query tlv found %s", trace_array(data_ptr, data_len));
|
||||
|
||||
if (query_info.tlvLen < 6) {
|
||||
tr_warn("malformed query tlv"); // query tlv contains query id (length 4 bytes), query options - atleast 2 bytes
|
||||
return -2;
|
||||
}
|
||||
|
||||
query_options_len = thread_tmfcop_tlv_find(query_info.dataPtr, query_info.tlvLen, LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_OPTIONS, &query_options_ptr);
|
||||
|
||||
if (!query_options_len) {
|
||||
tr_warn("No Option TLV found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this = thread_lowpower_data_metrics_create(address);
|
||||
|
||||
if (!this) {
|
||||
//query aready exists
|
||||
tr_error("query not created");
|
||||
return -3;
|
||||
}
|
||||
tr_debug("saving link metrics requested");
|
||||
memcpy(this->address, address, 16);
|
||||
this->timeout_timer = 2; // We wait max 2 seconds for single probe Although 0 is enough as response should be written immediately
|
||||
this->link_metrics_ready = true;
|
||||
this->req_metrics_len = query_options_len; // first 4 bytes are for query id, 5th byte is query options sub tlv type
|
||||
thread_tmfcop_tlv_data_get_uint16(query_info.dataPtr, query_info.tlvLen, LINK_METRIC_SUB_TLV_LINK_METRIC_QUERY_ID, &this->query_ID);
|
||||
|
||||
/* Go through the requested data - first 4 bytes id and next two bytes type and length of query options subtlv.
|
||||
* So start from the 7th byte*/
|
||||
// query tlv contains query id (length 4 bytes), query options - atleast 2 bytes
|
||||
if (this->req_metrics_len > METRICS_LEN) {
|
||||
this->req_metrics_len = METRICS_LEN;
|
||||
}
|
||||
for (uint8_t i = 0; i < this->req_metrics_len; i++) {
|
||||
//save the read bytes for computing the results
|
||||
this->metrics_requested[i] = *query_options_ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_lowpower_mle_command_send(protocol_interface_info_entry_t *cur, uint8_t *address, uint8_t series_id, uint8_t series_flags, uint16_t timeout, uint8_t *metrics_ptr, uint8_t metrics_len)
|
||||
{
|
||||
uint32_t keySequence;
|
||||
uint16_t buf_id;
|
||||
uint8_t request_tlv[1];
|
||||
uint8_t mle_command = MLE_COMMAND_DATA_REQUEST;
|
||||
|
||||
if (series_flags || timeout) {
|
||||
mle_command = MLE_COMMAND_METRIC_MANAGEMENT_REQUEST;
|
||||
}
|
||||
//Leader data 10 bytes
|
||||
//query: query tlv (1 byte), query length (1 byte), query_id (4 bytes), query_options (1 byte) + query_len (1 byte) + query (length bytes) = 8 + length
|
||||
//request tlv 3 bytes
|
||||
buf_id = mle_service_msg_allocate(cur->id, 10 + 8 + metrics_len + 3 + (1 + thread_leader_data_tlv_size(cur)), false, mle_command);
|
||||
|
||||
if (0 == buf_id) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t *ptr = mle_service_get_data_pointer(buf_id);
|
||||
//request TLV requesting link metrics report
|
||||
if (series_flags || timeout) {
|
||||
// Always enough room
|
||||
ptr = thread_lowpower_tlv_write_metrics_management_forward_probe_request(ptr, series_id, series_flags, timeout, metrics_ptr, metrics_len);
|
||||
} else {
|
||||
request_tlv[0] = MLE_TYPE_LINK_METRICS_REPORT;
|
||||
ptr = mle_tlv_req_tlv(ptr, request_tlv, 1);
|
||||
ptr = thread_lowpower_tlv_write_link_metrics_query(ptr, metrics_ptr, metrics_len, series_id);
|
||||
ptr = thread_active_timestamp_write(cur, ptr); // 10 bytes
|
||||
//SET Leader Data
|
||||
ptr = thread_leader_data_tlv_write(ptr, cur);
|
||||
}
|
||||
|
||||
if (0 != mle_service_update_length_by_ptr(buf_id, ptr)) {
|
||||
tr_error("Buffer overflow at message write");
|
||||
}
|
||||
|
||||
mac_data_poll_init_protocol_poll(cur);
|
||||
mle_service_set_msg_destination_address(buf_id, address);
|
||||
//Set Security
|
||||
thread_management_get_current_keysequence(cur->id, &keySequence);
|
||||
mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
|
||||
mle_service_send_message(buf_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int thread_lowpower_mle_probe_send(protocol_interface_info_entry_t *cur, uint8_t *address)
|
||||
{
|
||||
uint32_t keySequence;
|
||||
uint16_t buf_id;
|
||||
|
||||
//Leader data 10 bytes
|
||||
//query: query tlv (1 byte), query length (1 byte), query_id (4 bytes), query_options (1 byte) + query_len (1 byte) + query (length bytes) = 8 + length
|
||||
//request tlv 3 bytes
|
||||
buf_id = mle_service_msg_allocate(cur->id, 10, false, MLE_COMMAND_PROBE);
|
||||
|
||||
if (0 == buf_id) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t *ptr = mle_service_get_data_pointer(buf_id);
|
||||
ptr = thread_leader_data_tlv_write(ptr, cur);
|
||||
|
||||
if (0 != mle_service_update_length_by_ptr(buf_id, ptr)) {
|
||||
tr_error("Buffer overflow at message write");
|
||||
}
|
||||
|
||||
mac_data_poll_init_protocol_poll(cur);
|
||||
mle_service_set_msg_destination_address(buf_id, address);
|
||||
//Set Security
|
||||
thread_management_get_current_keysequence(cur->id, &keySequence);
|
||||
mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
|
||||
mle_service_send_message(buf_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int thread_lowpower_test_probe_send(int8_t interface_id, uint8_t *address, uint8_t *metrics_ptr, uint8_t metrics_len, thread_lowpower_resp_cb response_cb)
|
||||
{
|
||||
return thread_lowpower_metrics_management_request_send(interface_id, address, 0, 0, 0, metrics_ptr, metrics_len, response_cb);
|
||||
}
|
||||
int thread_lowpower_metrics_management_request_send(int8_t interface_id, uint8_t *address, uint8_t series_id, uint8_t series_flags, uint16_t timeout, uint8_t *metrics_ptr, uint8_t metrics_len, thread_lowpower_resp_cb response_cb)
|
||||
{
|
||||
uint8_t dest_address[16] = {0};
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data_response_ptr->data_response_cb) {
|
||||
tr_warn("low power request already in process");
|
||||
return -2;
|
||||
}
|
||||
|
||||
//if no address is specified use parent's address
|
||||
if (!address) {
|
||||
thread_management_get_parent_address(interface_id, dest_address);
|
||||
} else {
|
||||
memcpy(dest_address, address, 16);
|
||||
}
|
||||
|
||||
tr_info("destination address = %s metrics queried %s", trace_ipv6(dest_address), trace_array(metrics_ptr, metrics_len));
|
||||
data_response_ptr->data_response_cb = response_cb;
|
||||
memcpy(data_response_ptr->destination_address, dest_address, 16);
|
||||
data_response_ptr->interface_id = interface_id;
|
||||
data_response_ptr->request_wait_timer = timeout; // wait for 3s for a response to the probe req
|
||||
data_response_ptr->series_flags = series_flags;
|
||||
data_response_ptr->series_id = series_id;
|
||||
data_response_ptr->probe_count = 3 + 1; // last probe is result rerieval message
|
||||
thread_lowpower_mle_command_send(cur, dest_address, series_id, series_flags, timeout, metrics_ptr, metrics_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thread_lowpower_request_timeout_cb(data_response_t *data_req, uint8_t *metrics_ptr, uint8_t metrics_len)
|
||||
{
|
||||
if (metrics_len == 0) {
|
||||
tr_warn("Clearing timers without response");
|
||||
}
|
||||
if (data_response_ptr->data_response_cb) {
|
||||
data_response_ptr->data_response_cb(data_req->destination_address, data_req->interface_id, metrics_ptr, metrics_len);
|
||||
}
|
||||
data_req->request_wait_timer = 0;
|
||||
data_req->data_response_cb = NULL;
|
||||
memset(data_req->destination_address, 0, 16);
|
||||
data_req->interface_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void thread_lowpower_process_response(uint8_t *src_address, int8_t instance_id, uint8_t *data_ptr, uint16_t data_len)
|
||||
{
|
||||
(void) instance_id;
|
||||
mle_tlv_info_t linkMetricsReport;
|
||||
if (memcmp(src_address, data_response_ptr->destination_address, 16) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mle_tlv_read_tlv(MLE_TYPE_LINK_METRICS_REPORT, data_ptr, data_len, &linkMetricsReport)) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread_lowpower_request_timeout_cb(data_response_ptr, data_ptr, data_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int thread_lowpower_process_request(mle_message_t *mle_msg)
|
||||
{
|
||||
if (!mle_msg->packet_src_address) {
|
||||
return -1;
|
||||
}
|
||||
if (mle_msg->message_type != MLE_COMMAND_DATA_REQUEST &&
|
||||
mle_msg->message_type != MLE_COMMAND_METRIC_MANAGEMENT_REQUEST) {
|
||||
// No need to process
|
||||
return 0;
|
||||
}
|
||||
// Process single shot queries
|
||||
thread_lowpower_requested_single_query_save(mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length);
|
||||
// Check if we have metrics management query
|
||||
thread_lowpower_requested_metrics_management_query_save(mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length);
|
||||
|
||||
if (mle_tlv_type_requested(MLE_TYPE_LINK_METRICS_REPORT, mle_msg->data_ptr, mle_msg->data_length)) {
|
||||
//request made for metrics report
|
||||
tr_debug("link metrics report requested");
|
||||
data_metrics_t *metrics = thread_lowpower_data_metrics_find_by_source_address(mle_msg->packet_src_address);
|
||||
if (metrics) {
|
||||
// make report ready so the next data response message will include the report
|
||||
tr_debug("link metrics report ready");
|
||||
metrics->link_metrics_ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_lowpower_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
|
||||
{
|
||||
(void) cur;
|
||||
if (data_response_ptr->request_wait_timer > 0) {
|
||||
if (data_response_ptr->series_flags) {
|
||||
if (data_response_ptr->probe_count > 0) {
|
||||
if (data_response_ptr->probe_count == 1) {
|
||||
// Send response retrieval after last probe
|
||||
thread_lowpower_mle_command_send(cur, data_response_ptr->destination_address, data_response_ptr->series_id, 0, 0, NULL, 0);
|
||||
|
||||
} else {
|
||||
thread_lowpower_mle_probe_send(cur, data_response_ptr->destination_address);
|
||||
}
|
||||
data_response_ptr->probe_count--;
|
||||
}
|
||||
// Send probe we only support MLE probe
|
||||
}
|
||||
|
||||
if (data_response_ptr->request_wait_timer > ticks) {
|
||||
data_response_ptr->request_wait_timer -= ticks;
|
||||
} else {
|
||||
thread_lowpower_request_timeout_cb(data_response_ptr, NULL, 0);
|
||||
}
|
||||
}
|
||||
ns_list_foreach_safe(data_metrics_t, low_power_metric_ptr, &thread_lowpower_data_metrics_instance_list) {
|
||||
if (low_power_metric_ptr->timeout_timer > ticks) {
|
||||
low_power_metric_ptr->timeout_timer -= ticks;
|
||||
} else {
|
||||
//query is timed out.
|
||||
thread_lowpower_data_metrics_delete(low_power_metric_ptr->address);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t thread_lowpower_link_metrics_length(protocol_interface_info_entry_t *cur, uint8_t *destination_address)
|
||||
{
|
||||
(void) cur;
|
||||
data_metrics_t *metrics = thread_lowpower_data_metrics_find_by_source_address(destination_address);
|
||||
if (!metrics) {
|
||||
return 0;
|
||||
}
|
||||
if (!metrics->link_metrics_ready) {
|
||||
return 0;
|
||||
}
|
||||
//link metrics report (4 bytes)
|
||||
return 4 + metrics->req_metrics_len * 2;
|
||||
|
||||
}
|
||||
|
||||
uint8_t *thread_lowpower_link_metrics_write(protocol_interface_info_entry_t *cur, uint8_t *destination_address, uint8_t *ptr)
|
||||
{
|
||||
(void)cur;
|
||||
data_metrics_t *metrics = thread_lowpower_data_metrics_find_by_source_address(destination_address);
|
||||
if (!metrics) {
|
||||
return ptr;
|
||||
}
|
||||
if (!metrics->link_metrics_ready) {
|
||||
tr_debug("link metrics not ready for destination");
|
||||
return ptr;
|
||||
}
|
||||
*ptr++ = MLE_TYPE_LINK_METRICS_REPORT;
|
||||
uint8_t req_metrics_len = metrics->req_metrics_len; // first 4 bytes are for query id, 5th byte is query options sub tlv type
|
||||
*ptr++ = req_metrics_len * 4; // metric report subtlv, metric report length, metric, and response - each one byte
|
||||
|
||||
/* Go through the requested data - first 4 bytes id and next two bytes type and length of query options subtlv.
|
||||
* So start from the 7th byte*/
|
||||
// assuming one byte result follows one byte request flag
|
||||
for (uint8_t i = 0; i < req_metrics_len; i++) {
|
||||
//save the read bytes for computing the results
|
||||
*ptr++ = LINK_METRIC_SUB_TLV_LINK_METRIC_REPORT;
|
||||
*ptr++ = 2; // report length 2 bytes
|
||||
*ptr++ = metrics->metrics_requested[i];
|
||||
*ptr++ = metrics->metrics_value[i];
|
||||
}
|
||||
|
||||
tr_debug("link metrics requested %s", trace_array(metrics->metrics_requested, metrics->req_metrics_len));
|
||||
tr_debug("link metrics values %s", trace_array(metrics->metrics_value, metrics->req_metrics_len));
|
||||
|
||||
thread_lowpower_data_metrics_delete(metrics->address);
|
||||
// this assumes request flags are written first followed by results
|
||||
// for (uint8_t i = (6 + req_metrics_len); i < (6 + req_metrics_len*2); i++) {
|
||||
// *ptr++ = thread_lowpower_data_metrics_requested_ptr->thread_link_metrics_responses[i-(6 + req_metrics_len)] ; //add zeros as results - needs to be updated
|
||||
// }
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int thread_lowpower_metrics_management_query_response_msg(protocol_interface_info_entry_t *cur, uint8_t *dst_address)
|
||||
{
|
||||
uint16_t length = 16; // Leader data 10 bytes + link metrics status 6 bytes
|
||||
uint8_t *ptr;
|
||||
|
||||
//link metrics info
|
||||
length += thread_lowpower_link_metrics_length(cur, dst_address);
|
||||
|
||||
uint16_t bufId = mle_service_msg_allocate(cur->id, length, false, MLE_COMMAND_METRIC_MANAGEMENT_RESPONSE);
|
||||
|
||||
if (bufId == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("Send MLE Management Query response, %s", trace_ipv6(dst_address));
|
||||
ptr = mle_service_get_data_pointer(bufId);
|
||||
|
||||
ptr = thread_leader_data_tlv_write(ptr, cur);
|
||||
ptr = thread_lowpower_link_metrics_write(cur, dst_address, ptr);
|
||||
ptr = thread_lowpower_tlv_write_metrics_management_status(ptr, 0);
|
||||
|
||||
if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
|
||||
tr_debug("Buffer overflow at message write");
|
||||
}
|
||||
mle_service_set_msg_destination_address(bufId, dst_address);
|
||||
//Set Security
|
||||
uint32_t keySequence;
|
||||
thread_management_get_current_keysequence(cur->id, &keySequence);
|
||||
mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
|
||||
|
||||
mle_service_send_message(bufId);
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void thread_lowpower_metrics_management_query_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
|
||||
{
|
||||
(void)cur;
|
||||
(void)security_headers;
|
||||
(void)linkMargin;
|
||||
|
||||
tr_info("Recv MLE Metrics Management Query");
|
||||
|
||||
thread_lowpower_metrics_management_query_response_msg(cur, mle_msg->packet_src_address);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_THREAD_V2 */
|
|
@ -36,6 +36,7 @@
|
|||
* Dummy implementation for thread_lowpower_api.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_THREAD_V2
|
||||
int thread_lowpower_test_probe_send(int8_t interface_id, uint8_t *address, uint8_t *metrics_ptr, uint8_t metrics_len, thread_lowpower_resp_cb response_cb)
|
||||
{
|
||||
(void)interface_id;
|
||||
|
@ -58,3 +59,4 @@ int thread_lowpower_metrics_management_request_send(int8_t interface_id, uint8_t
|
|||
(void)response_cb;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,61 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
/** \brief function to process data response received for link metrics
|
||||
*
|
||||
* \param src_address address source address of the data response message
|
||||
* \param instance_id instance_id of the interface
|
||||
* \param data_ptr response data
|
||||
* \param data_len length of the response received
|
||||
*
|
||||
*/
|
||||
void thread_lowpower_process_response(uint8_t *src_address, int8_t instance_id, uint8_t *data_ptr, uint16_t data_len);
|
||||
|
||||
/** \brief function to process data request received for link metrics.
|
||||
* Function processes only data request messages
|
||||
*
|
||||
* \param mle_msg
|
||||
*
|
||||
*/
|
||||
int thread_lowpower_process_request(mle_message_t *mle_msg);
|
||||
|
||||
/** \brief function to check if the lowpower metrics requested is ready
|
||||
*
|
||||
* \param cur protocol interface
|
||||
* \param ticks ticks for timer
|
||||
*
|
||||
*/
|
||||
int thread_lowpower_timer(protocol_interface_info_entry_t *cur, uint32_t ticks);
|
||||
|
||||
/** \brief function writes the link metrics tlv if available
|
||||
*
|
||||
* \param cur protocol interface
|
||||
* \param destination_address destination address for link metrics
|
||||
* \param ptr location to which the metrics are written
|
||||
*
|
||||
*/
|
||||
uint8_t *thread_lowpower_link_metrics_write(protocol_interface_info_entry_t *cur, uint8_t *destination_address, uint8_t *ptr);
|
||||
|
||||
/** \brief function calculates the link metrics length if metrics available
|
||||
*
|
||||
* \param cur protocol interface
|
||||
* \param destination_address destination address for link metrics
|
||||
*
|
||||
*/
|
||||
uint8_t thread_lowpower_link_metrics_length(protocol_interface_info_entry_t *cur, uint8_t *destination_address);
|
||||
|
||||
/** \brief function calculates the link metrics length if metrics available
|
||||
*
|
||||
* \param cur protocol interface
|
||||
* \param destination_address destination address for link metrics
|
||||
*
|
||||
*/
|
||||
void thread_lowpower_metrics_management_query_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
|
||||
|
||||
#else /* HAVE_THREAD_V2 */
|
||||
|
||||
#define thread_lowpower_process_request(mle_msg)
|
||||
#define thread_lowpower_process_response(src_address, instance_id, data_ptr, data_len)
|
||||
#define thread_lowpower_timer(cur, ticks)
|
||||
|
@ -45,6 +100,9 @@ extern "C" {
|
|||
#define thread_lowpower_link_metrics_length(cur, destination_address) (0)
|
||||
#define thread_lowpower_metrics_management_query_request_process(cur, mle_msg, security_headers, linkMargin)
|
||||
|
||||
#endif /* HAVE_THREAD_V2 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -605,7 +605,6 @@ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t ad
|
|||
THREAD_URI_ADDRESS_NOTIFICATION, COAP_CT_OCTET_STREAM,
|
||||
payload, ptr - payload, thread_management_client_proactive_an_cb);
|
||||
}
|
||||
|
||||
void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id)
|
||||
{
|
||||
thread_management_t *this = thread_management_find(interface_id);
|
||||
|
@ -631,4 +630,63 @@ void thread_management_client_old_partition_data_clean(int8_t interface_id)
|
|||
coap_service_request_delete_by_service_id(this->coap_service_id);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
void thread_management_client_addr_ntf_send(int8_t interface_id, uint8_t *destination_address, const uint8_t *addr_data_ptr, uint8_t bbr_status)
|
||||
{
|
||||
uint8_t payload[16 + 1]; // Target eid + Status
|
||||
uint8_t *ptr;
|
||||
uint8_t br_ml_addr[16];
|
||||
uint8_t seq;
|
||||
uint32_t delay_timer;
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!thread_bootstrap_is_domain_prefix(cur, addr_data_ptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(cur, br_ml_addr, &seq, &delay_timer, NULL)) {
|
||||
// No pBBR present
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = payload;
|
||||
ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, addr_data_ptr);
|
||||
ptr = thread_tmfcop_tlv_data_write_uint8(ptr, TMFCOP_TLV_STATUS, bbr_status);
|
||||
|
||||
coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_ADDRESS_SHORT,
|
||||
destination_address, THREAD_MANAGEMENT_PORT,
|
||||
COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST,
|
||||
THREAD_URI_BBR_DOMAIN_ADDRESS_NOTIFICATION, COAP_CT_OCTET_STREAM,
|
||||
payload, ptr - payload, NULL);
|
||||
return;
|
||||
}
|
||||
static int thread_bootstrap_mlr_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) service_id;
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
(void) response_ptr;
|
||||
|
||||
tr_debug("Thread MLR callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_management_client_mlr_req_send(int8_t interface_id, const uint8_t br_addr[16], const uint8_t *address, uint8_t address_len)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !br_addr || !address) {
|
||||
return -1;
|
||||
}
|
||||
tr_debug("thread MLR.req send");
|
||||
|
||||
coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_NONE, br_addr, THREAD_MANAGEMENT_PORT,
|
||||
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_BBR_MCAST_LISTENER_REPORT, COAP_CT_OCTET_STREAM, address, address_len, thread_bootstrap_mlr_cb);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include <ns_types.h>
|
||||
#include "thread_management_if.h"
|
||||
#include "net_interface.h"
|
||||
|
||||
#define TRACE_GROUP_THREAD_MANAGEMENT_CLIENT "TMFs"
|
||||
|
||||
|
@ -223,4 +224,27 @@ void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t
|
|||
* \param interface_id interface id of this Thread instance.
|
||||
*/
|
||||
void thread_management_client_old_partition_data_clean(int8_t interface_id);
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
/** Send address notification message.
|
||||
*
|
||||
* Sends address notification message
|
||||
*
|
||||
* \param interface_id interface id of this Thread instance.
|
||||
*/
|
||||
void thread_management_client_addr_ntf_send(int8_t interface_id, uint8_t *destination_address, const uint8_t *addr_data_ptr, uint8_t bbr_status);
|
||||
/** Send multicast registration message
|
||||
*
|
||||
* include all the addresses that are registered to the bbr
|
||||
*
|
||||
* \param interface_id interface id of this Thread instance.
|
||||
*/
|
||||
int thread_management_client_mlr_req_send(int8_t interface_id, const uint8_t br_addr[16], const uint8_t *address, uint8_t address_len);
|
||||
#else
|
||||
|
||||
#define thread_management_client_addr_ntf_send(interface_id, destination_address, addr_data_ptr, bbr_status) (void(0))
|
||||
#define thread_management_client_mlr_req_send(interface_id, br_addr, address, address_len) (void(0))
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* THREAD_MANAGEMENT_CLIENT_H_ */
|
||||
|
|
|
@ -58,13 +58,12 @@
|
|||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "Service_Libs/mle_service/mle_service_security.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_constants.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
||||
#include "Service_Libs/mle_service/mle_service_security.h"
|
||||
#include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up
|
||||
#include "MLE/mle.h"
|
||||
#include "MLE/mle_tlv.h"
|
||||
|
@ -1360,7 +1359,7 @@ int thread_management_device_certificate_set(int8_t interface_id, const unsigned
|
|||
return -1;
|
||||
}
|
||||
|
||||
return thread_extension_bootstrap_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len);
|
||||
return thread_ccm_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len);
|
||||
|
||||
#else
|
||||
(void) interface_id;
|
||||
|
@ -1384,12 +1383,12 @@ int thread_management_network_certificate_set(int8_t interface_id, const unsigne
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret_val = thread_extension_bootstrap_network_certificate_set(cur, network_certificate_ptr, network_certificate_len);
|
||||
ret_val = thread_ccm_network_certificate_set(cur, network_certificate_ptr, network_certificate_len);
|
||||
if (0 > ret_val) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return thread_extension_bootstrap_network_private_key_set(cur, priv_key_ptr, priv_key_len);
|
||||
return thread_ccm_network_private_key_set(cur, priv_key_ptr, priv_key_len);
|
||||
#else
|
||||
(void) interface_id;
|
||||
return -1;
|
||||
|
@ -1421,7 +1420,7 @@ int thread_management_partition_weighting_set(int8_t interface_id, uint8_t parti
|
|||
cur->thread_info->partition_weighting = partition_weighting;
|
||||
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
if (trig_network_scan && thread_extension_enabled(cur)) {
|
||||
if (trig_network_scan && thread_common_ccm_enabled(cur)) {
|
||||
thread_nvm_store_link_info_clear();
|
||||
// bootstrap active and weighting has changed
|
||||
thread_bootstrap_reset_restart(interface_id);
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "6LoWPAN/Thread/thread_management_server.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_leader_service.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_discovery.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_border_router_api_internal.h"
|
||||
|
@ -64,6 +63,9 @@
|
|||
#include "thread_beacon.h"
|
||||
#include "thread_bootstrap.h"
|
||||
#include "thread_management_server.h"
|
||||
#include "thread_management_client.h"
|
||||
#include "thread_ccm.h"
|
||||
#include "thread_nvm_store.h"
|
||||
#include "mac_api.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
|
@ -466,6 +468,394 @@ send_response:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
static int thread_management_server_mtd_dua_ntf_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
|
||||
{
|
||||
(void) service_id;
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
(void) response_ptr;
|
||||
uint16_t addr_len;
|
||||
uint8_t *addr_data_ptr;
|
||||
uint8_t dua_status = THREAD_ST_DUA_SUCCESS;
|
||||
tr_debug("Thread MTD n/dn callback");
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_client_get_interface_id_by_service_id(service_id));
|
||||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
addr_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_TARGET_EID, &addr_data_ptr);
|
||||
|
||||
if (addr_len < 16) {
|
||||
tr_warn("Invalid target eid in DUA.ntf cb message");
|
||||
return -2;
|
||||
}
|
||||
|
||||
thread_tmfcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_STATUS, &dua_status);
|
||||
|
||||
if (dua_status == THREAD_ST_DUA_DUPLICATE) {
|
||||
// generate new dua address
|
||||
cur->dad_failures++;
|
||||
thread_bootstrap_dua_address_generate(cur, addr_data_ptr, 64);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thread_management_server_reset_timeout_cb(void *arg)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t *)arg;
|
||||
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete all domain stuff and start discovery.
|
||||
thread_ccm_network_certificate_set(cur, NULL, 0);
|
||||
thread_ccm_network_private_key_set(cur, NULL, 0);
|
||||
thread_nvm_store_mleid_rloc_map_remove();
|
||||
thread_nvm_store_link_info_clear();
|
||||
thread_joiner_application_link_configuration_delete(cur->id);
|
||||
thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_KICK, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Commissioner requests to leave this domain
|
||||
*/
|
||||
static int thread_management_server_reset_req_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
|
||||
uint8_t payload[3] = {0};
|
||||
uint8_t *ptr = payload;
|
||||
uint8_t *signature_ptr = NULL;
|
||||
uint16_t session_id = 0;
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id));
|
||||
|
||||
if (!cur || !request_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("Received MGMT_RESET.req");
|
||||
|
||||
// Verify request TLV's: Commissioner Session ID TLV - Commissioner Token TLV (optional) - Commissioner Signature TLV
|
||||
thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id);
|
||||
thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMM_SIGNATURE, &signature_ptr);
|
||||
|
||||
if ((session_id != thread_info(cur)->registered_commissioner.session_id) /*|| (signature_ptr == NULL)*/) { // todo: signature may not come in this early phase of implementors
|
||||
tr_debug("Request parse failed");
|
||||
ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff);
|
||||
}
|
||||
|
||||
// Downgrade if router
|
||||
if (thread_am_router(cur)) {
|
||||
thread_bootstrap_attached_downgrade_router(cur);
|
||||
}
|
||||
|
||||
// Delete all data and start reattach
|
||||
// Get some time to send response and keep the Commissioner happy
|
||||
cur->thread_info->ccm_info->reset_timeout = eventOS_timeout_ms(thread_management_server_reset_timeout_cb, 5000, cur);
|
||||
|
||||
// Send response
|
||||
coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, payload, ptr - payload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Commissioner requests to get new certificate from Registrar, but to stay in the same domain
|
||||
*/
|
||||
static int thread_management_server_reenroll_req_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
|
||||
uint8_t pbbr_addr[16] = {0};
|
||||
uint8_t status_tlv[3] = {0};
|
||||
uint8_t *ptr = status_tlv;
|
||||
uint8_t *signature_ptr = NULL;
|
||||
uint16_t session_id = 0;
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id));
|
||||
|
||||
if (!cur || !request_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("Received MGMT_REENROLL.req");
|
||||
|
||||
// Verify request TLV's: Commissioner Session ID TLV - Commissioner Token TLV (optional) - Commissioner Signature TLV
|
||||
thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id);
|
||||
thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMM_SIGNATURE, &signature_ptr);
|
||||
|
||||
if ((session_id != thread_info(cur)->registered_commissioner.session_id) ||/* (signature_ptr == NULL) || */
|
||||
thread_common_primary_bbr_get(cur, pbbr_addr, NULL, NULL, NULL)) {
|
||||
tr_debug("Request parse failed");
|
||||
ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff);
|
||||
goto send_response;
|
||||
}
|
||||
|
||||
thread_ccm_reenrollment_start(cur, service_id, pbbr_addr);
|
||||
|
||||
send_response:
|
||||
|
||||
// send response
|
||||
coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, status_tlv, ptr - status_tlv);
|
||||
return 0;
|
||||
}
|
||||
static void thread_management_server_ccm_register(int8_t interface_id, int8_t coap_service_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->thread_info->ccm_info) {
|
||||
return;
|
||||
}
|
||||
cur->thread_info->ccm_info->coap_service_id = coap_service_id;
|
||||
coap_service_register_uri(thread_info(cur)->ccm_info->coap_service_id, THREAD_URI_RESET_REQ, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_reset_req_cb);
|
||||
coap_service_register_uri(thread_info(cur)->ccm_info->coap_service_id, THREAD_URI_REENROLL_REQ, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_reenroll_req_cb);
|
||||
}
|
||||
static void thread_management_server_mtd_service_register(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
coap_service_register_uri(thread_management_server_service_id_get(cur->id), THREAD_URI_BBR_DOMAIN_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_mtd_dua_ntf_cb);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
|
||||
static int thread_management_server_ccm_relay_tx_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
ns_address_t destination_address = { .address = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
|
||||
uint8_t *udp_data_ptr;
|
||||
uint16_t udp_data_len;
|
||||
uint8_t *iid_ptr;
|
||||
uint8_t iid_len;
|
||||
uint16_t port;
|
||||
uint8_t port_len;
|
||||
int8_t socket_id;
|
||||
(void)source_address;
|
||||
(void)source_port;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id));
|
||||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
iid_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &iid_ptr);
|
||||
port_len = thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &port);
|
||||
udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_data_ptr);
|
||||
// unwrap message and send to joiner socket.
|
||||
if (8 > iid_len || 2 > port_len || 0 == udp_data_len) {
|
||||
tr_err("Relay TX invalid message iid:%d, port:%d data_len:%d", iid_len, port_len, udp_data_len);
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(THREAD_URI_BBR_NMK_TX_NTF, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) {
|
||||
socket_id = cur->thread_info->ccm_info->listen_socket_nmkp;
|
||||
} else if (strncmp(THREAD_URI_BBR_TRI_TX_NTF, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) {
|
||||
socket_id = cur->thread_info->ccm_info->listen_socket_ae;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&destination_address.address[8], iid_ptr, 8);
|
||||
destination_address.identifier = port;
|
||||
destination_address.type = ADDRESS_IPV6;
|
||||
int8_t err = socket_sendto(socket_id, &destination_address, udp_data_ptr, udp_data_len);
|
||||
if (err < 0) {
|
||||
tr_err("Relay TX sendto failed %d", err);
|
||||
}
|
||||
|
||||
tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len);
|
||||
|
||||
return -1; // OK no response sent
|
||||
}
|
||||
|
||||
static void thread_management_server_relay_socket_cb(void *cb_res)
|
||||
{
|
||||
socket_callback_t *sckt_data = 0;
|
||||
ns_address_t source_address;
|
||||
uint8_t relay_destination_address[16];
|
||||
uint8_t *data_ptr = NULL;
|
||||
uint16_t data_len = 0;
|
||||
uint8_t *ptr;
|
||||
uint8_t *payload_ptr;
|
||||
uint16_t payload_len;
|
||||
char *destination_uri_ptr = THREAD_URI_RELAY_RECEIVE;
|
||||
sckt_data = cb_res;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(sckt_data->interface_id);
|
||||
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
if (sckt_data->socket_id == cur->thread_info->ccm_info->listen_socket_nmkp) {
|
||||
destination_uri_ptr = THREAD_URI_BBR_NMK_RX_NTF;
|
||||
} else if (sckt_data->socket_id == cur->thread_info->ccm_info->listen_socket_ae) {
|
||||
destination_uri_ptr = THREAD_URI_BBR_TRI_RX_NTF;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) {
|
||||
data_ptr = ns_dyn_mem_alloc(sckt_data->d_len);
|
||||
if (!data_ptr) {
|
||||
tr_err("Out of memory");
|
||||
return;
|
||||
}
|
||||
data_len = socket_read(sckt_data->socket_id, &source_address, data_ptr, sckt_data->d_len);
|
||||
}
|
||||
if (!data_ptr || data_len < 1) {
|
||||
tr_err("No data received");
|
||||
return;
|
||||
}
|
||||
|
||||
thread_addr_write_mesh_local_16(relay_destination_address, 0xfc38, cur->thread_info);
|
||||
|
||||
payload_len = 4 + data_len + 4 + 8 + 4 + 2 + 4 + 2; //Joiner DTLS Encapsulation TLV Joiner UDP Port TLV Joiner IID TLV Joiner Router Locator TLV
|
||||
payload_ptr = ns_dyn_mem_alloc(payload_len);
|
||||
|
||||
if (!payload_ptr) {
|
||||
tr_err("Out of memory");
|
||||
ns_dyn_mem_free(data_ptr);
|
||||
return;
|
||||
}
|
||||
tr_debug("Relay TX recvfrom addr: %s, port:%d len:%d", trace_ipv6(source_address.address), source_address.identifier, data_len);
|
||||
thci_trace("joinerrouterJoinerDataRelayedInbound");
|
||||
ptr = payload_ptr;
|
||||
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr);
|
||||
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &source_address.address[8]);
|
||||
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, source_address.identifier);
|
||||
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, mac_helper_mac16_address_get(cur));
|
||||
|
||||
coap_service_request_send(cur->thread_info->ccm_info->coap_service_id, COAP_REQUEST_OPTIONS_NONE, relay_destination_address, THREAD_MANAGEMENT_PORT,
|
||||
COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, destination_uri_ptr, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL);
|
||||
ns_dyn_mem_free(payload_ptr);
|
||||
ns_dyn_mem_free(data_ptr);
|
||||
}
|
||||
|
||||
static void thread_management_server_joiner_router_ae_deinit(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (cur->thread_info->ccm_info->relay_port_ae > 0) {
|
||||
tr_debug("deinit AE");
|
||||
coap_service_unregister_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_TRI_TX_NTF);
|
||||
socket_close(cur->thread_info->ccm_info->listen_socket_ae);
|
||||
cur->thread_info->ccm_info->listen_socket_ae = -1;
|
||||
cur->thread_info->ccm_info->relay_port_ae = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_management_server_joiner_router_nmkp_deinit(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (cur->thread_info->ccm_info->relay_port_nmkp > 0) {
|
||||
tr_debug("deinit NMKP");
|
||||
coap_service_unregister_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_NMK_TX_NTF);
|
||||
socket_close(cur->thread_info->ccm_info->listen_socket_nmkp);
|
||||
cur->thread_info->ccm_info->listen_socket_nmkp = -1;
|
||||
cur->thread_info->ccm_info->relay_port_nmkp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int thread_management_server_ccm_joiner_router_init(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
int8_t securityLinkLayer = 0;
|
||||
|
||||
if (!cur->thread_info->ccm_info || thread_info(cur)->version < THREAD_VERSION_1_2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(cur, NULL, NULL, NULL, NULL)) {
|
||||
// Need to disable Joiner router either because port changed or moving to disabled
|
||||
thread_management_server_joiner_router_ae_deinit(cur);
|
||||
thread_management_server_joiner_router_nmkp_deinit(cur);
|
||||
// Joiner router should be disabled
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is this a CCM network?
|
||||
uint16_t securityPolicy = thread_joiner_application_security_policy_get(cur->id);
|
||||
if (securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED) {
|
||||
// Not a CCM network, de-initialize
|
||||
thread_management_server_joiner_router_ae_deinit(cur);
|
||||
thread_management_server_joiner_router_nmkp_deinit(cur);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (thread_ccm_network_certificate_available(cur) == false) {
|
||||
// No domain certificate available
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(securityPolicy & THREAD_SECURITY_POLICY_AE_DISABLED)) {
|
||||
if (cur->thread_info->ccm_info->listen_socket_ae < 0) {
|
||||
// Start AE relay
|
||||
cur->thread_info->ccm_info->listen_socket_ae = socket_open(SOCKET_UDP, THREAD_DEFAULT_AE_PORT, thread_management_server_relay_socket_cb);
|
||||
if (cur->thread_info->ccm_info->listen_socket_ae >= 0) {
|
||||
cur->thread_info->ccm_info->relay_port_ae = THREAD_DEFAULT_AE_PORT;
|
||||
socket_setsockopt(cur->thread_info->ccm_info->listen_socket_ae, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t));
|
||||
// The regular TX is usable from joiner router, because it is stateless, but it neds to be forced on
|
||||
coap_service_register_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_TRI_TX_NTF, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_ccm_relay_tx_cb);
|
||||
} else {
|
||||
tr_warn("Joiner AE failed");
|
||||
cur->thread_info->ccm_info->relay_port_ae = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thread_management_server_joiner_router_ae_deinit(cur);
|
||||
}
|
||||
|
||||
if (!(securityPolicy & THREAD_SECURITY_POLICY_NMP_DISABLED)) {
|
||||
if (cur->thread_info->ccm_info->listen_socket_nmkp < 0) {
|
||||
// Start nmkp relay
|
||||
cur->thread_info->ccm_info->listen_socket_nmkp = socket_open(SOCKET_UDP, THREAD_DEFAULT_NMKP_PORT, thread_management_server_relay_socket_cb);
|
||||
if (cur->thread_info->ccm_info->listen_socket_nmkp >= 0) {
|
||||
cur->thread_info->ccm_info->relay_port_nmkp = THREAD_DEFAULT_NMKP_PORT;
|
||||
socket_setsockopt(cur->thread_info->ccm_info->listen_socket_nmkp, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t));
|
||||
// The regular TX is usable from joiner router, because it is stateless, but it neds to be forced on
|
||||
coap_service_register_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_NMK_TX_NTF, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_ccm_relay_tx_cb);
|
||||
} else {
|
||||
tr_warn("Joiner NMKP failed");
|
||||
cur->thread_info->ccm_info->relay_port_nmkp = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thread_management_server_joiner_router_nmkp_deinit(cur);
|
||||
}
|
||||
|
||||
tr_info("init commercial joiner router ae:%d nmkp:%d", cur->thread_info->ccm_info->relay_port_ae, cur->thread_info->ccm_info->relay_port_nmkp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // HAVE_THREAD_ROUTER
|
||||
|
||||
#else
|
||||
#define thread_management_server_ccm_register(interface_id, coap_service_id) ((void)0)
|
||||
#endif // HAVE_THREAD_V2
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
/* Public APIs */
|
||||
|
||||
int thread_management_server_ccm_service_init(int8_t interface_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->thread_info->ccm_info || !cur->thread_info->ccm_info->coap_service_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ||
|
||||
cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
|
||||
thread_management_server_mtd_service_register(cur);
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
} else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
|
||||
thread_management_server_ccm_joiner_router_init(cur);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // HAVE_THREAD_V2
|
||||
|
||||
static int thread_start_mac_with_link_configuration(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration)
|
||||
{
|
||||
mlme_start_t start_req;
|
||||
|
@ -1220,7 +1610,7 @@ int thread_management_server_init(int8_t interface_id)
|
|||
return -3;
|
||||
}
|
||||
#endif
|
||||
thread_extension_init(interface_id, this->coap_service_id);
|
||||
thread_management_server_ccm_register(interface_id, this->coap_service_id);
|
||||
// All thread devices
|
||||
coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb);
|
||||
|
||||
|
|
|
@ -134,6 +134,12 @@ bool thread_management_server_source_address_check(int8_t interface_id, uint8_t
|
|||
*/
|
||||
int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr);
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
int thread_management_server_ccm_service_init(int8_t interface_id);
|
||||
#else
|
||||
#define thread_management_server_ccm_service_init(interface_id)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "6LoWPAN/Thread/thread_leader_service.h"
|
||||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_host_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_network_synch.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
|
@ -744,7 +743,7 @@ static bool thread_address_registration_tlv_check(protocol_interface_info_entry_
|
|||
}
|
||||
}
|
||||
}
|
||||
thread_extension_child_address_registration_response_process(cur);
|
||||
thread_bootstrap_child_address_registration_response_process(cur);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
|
|
@ -53,11 +53,11 @@
|
|||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "6LoWPAN/Thread/thread_nd.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_resolution_client.h"
|
||||
#include "6LoWPAN/Thread/thread_resolution_server.h"
|
||||
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
|
@ -149,7 +149,7 @@ static void thread_nd_coap_notification_callback(int8_t interface_id, const uint
|
|||
if (old_entry_rloc != loc_addr) {
|
||||
uint8_t old_entry_ip[16];
|
||||
thread_addr_write_mesh_local_16(old_entry_ip, common_read_16_bit(entry->ll_address + 2), cur->thread_info);
|
||||
tr_warn("Proactive address change %s %04x->%04x", trace_ipv6(ip_addr), old_entry_rloc, loc_addr);
|
||||
tr_info("Proactive address change %s %04x->%04x", trace_ipv6(ip_addr), old_entry_rloc, loc_addr);
|
||||
thread_resolution_client_address_error(interface_id, old_entry_ip, ip_addr, ml_eid);
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t tar
|
|||
can_route_of_mesh = true;
|
||||
}
|
||||
|
||||
if (thread_extension_bbr_nd_query_process(cur, target_addr, *rloc)) {
|
||||
if (thread_bbr_commercial_nd_query_process(cur, target_addr, *rloc)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ static void thread_nd_address_error(int8_t interface_id, const uint8_t ip_addr[1
|
|||
if_address_entry_t *addr_entry = addr_get_entry(cur, ip_addr);
|
||||
if (addr_entry && memcmp(ml_eid, cur->iid_slaac, 8)) {
|
||||
addr_duplicate_detected(cur, ip_addr);
|
||||
thread_extension_dua_address_generate(cur, ip_addr, 64);
|
||||
thread_bootstrap_dua_address_generate(cur, ip_addr, 64);
|
||||
}
|
||||
|
||||
/* Scan IPv6 neighbour cache for registered entries of children */
|
||||
|
@ -577,6 +577,18 @@ void thread_nd_address_remove(protocol_interface_info_entry_t *cur_interface, ad
|
|||
}
|
||||
}
|
||||
|
||||
bool thread_pbbr_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16)
|
||||
{
|
||||
if (*addr16 == 0xfc38) {
|
||||
uint8_t addr[16];
|
||||
if (0 == thread_common_primary_bbr_get(cur, addr, NULL, NULL, NULL)) {
|
||||
*addr16 = common_read_16_bit(addr + 14);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int thread_nd_map_anycast_address(protocol_interface_info_entry_t *cur, uint16_t *addr16)
|
||||
{
|
||||
// Nothing implemented for now
|
||||
|
@ -613,7 +625,7 @@ int thread_nd_map_anycast_address(protocol_interface_info_entry_t *cur, uint16_t
|
|||
*addr16 = common_read_16_bit(cur->thread_info->registered_commissioner.border_router_address + 14);
|
||||
return 0;
|
||||
}
|
||||
if (thread_extension_aloc_map(cur, addr16)) {
|
||||
if (thread_pbbr_aloc_map(cur, addr16)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "ip6string.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_config.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_storage.h"
|
||||
|
@ -1962,7 +1961,7 @@ uint8_t thread_nd_context_id_allocate(thread_network_data_cache_entry_t *network
|
|||
}
|
||||
|
||||
//Allocate Free context id
|
||||
if (thread_extension_version_check(thread_version)) {
|
||||
if (thread_version >= THREAD_VERSION_1_2) {
|
||||
tempId = 2;
|
||||
} else {
|
||||
tempId = 1;
|
||||
|
|
|
@ -56,10 +56,8 @@
|
|||
#include "6LoWPAN/Thread/thread_network_synch.h"
|
||||
#include "6LoWPAN/Thread/thread_discovery.h"
|
||||
#include "6LoWPAN/Thread/thread_joiner_application.h"
|
||||
#include "6LoWPAN/Thread/thread_address_registration_client.h"
|
||||
#include "6LoWPAN/Thread/thread_management_client.h"
|
||||
#include "6LoWPAN/Thread/thread_management_server.h"
|
||||
#include "6LoWPAN/Thread/thread_extension.h"
|
||||
#include "6LoWPAN/Thread/thread_leader_service.h"
|
||||
#include "6LoWPAN/Thread/thread_beacon.h"
|
||||
#include "6LoWPAN/Thread/thread_network_data_lib.h"
|
||||
|
@ -67,7 +65,7 @@
|
|||
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "thread_management_if.h"
|
||||
#include "Common_Protocols/ipv6.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
|
@ -110,6 +108,13 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c
|
|||
static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info_entry_t *cur);
|
||||
static bool thread_child_id_request(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *entry_temp);
|
||||
|
||||
|
||||
#ifdef HAVE_THREAD_V2
|
||||
static bool thread_router_bootstrap_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur);
|
||||
#else
|
||||
#define thread_router_bootstrap_is_reed_upgrade_allowed(cur) (true)
|
||||
#endif
|
||||
|
||||
static bool thread_router_parent_address_check(protocol_interface_info_entry_t *cur, uint8_t *source_addr)
|
||||
{
|
||||
if (thread_info(cur)->thread_endnode_parent &&
|
||||
|
@ -1407,7 +1412,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
|
|||
tr_debug("Register %s", trace_ipv6(tempIPv6Address));
|
||||
//Register GP --> 16
|
||||
int retVal = thread_nd_address_registration(cur, tempIPv6Address, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
|
||||
thread_extension_address_registration(cur, tempIPv6Address, mac64, new_neighbour_created, retVal == -2);
|
||||
thread_bootstrap_address_registration(cur, tempIPv6Address, mac64, new_neighbour_created, retVal == -2);
|
||||
(void) retVal;
|
||||
} else {
|
||||
tr_debug("No Context %u", ctxId);
|
||||
|
@ -1428,7 +1433,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
|
|||
} else {
|
||||
//Register GP --> 16
|
||||
int retVal = thread_nd_address_registration(cur, ptr, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
|
||||
thread_extension_address_registration(cur, ptr, mac64, new_neighbour_created, retVal == -2);
|
||||
thread_bootstrap_address_registration(cur, ptr, mac64, new_neighbour_created, retVal == -2);
|
||||
(void) retVal;
|
||||
}
|
||||
|
||||
|
@ -1486,7 +1491,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
}
|
||||
|
||||
// check if security policy prevents sending of parent response
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
|
||||
tr_debug("Security policy prevents parent response; drop packet");
|
||||
return;
|
||||
}
|
||||
|
@ -1605,7 +1610,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
}
|
||||
|
||||
// check if security policy prevents sending of child id response
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
|
||||
tr_debug("Security policy prevents child id response; drop packet");
|
||||
return;
|
||||
}
|
||||
|
@ -2166,6 +2171,77 @@ int thread_router_bootstrap_link_synch_start(protocol_interface_info_entry_t *cu
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_THREAD_V2
|
||||
|
||||
static bool thread_router_bootstrap_is_version_high_for_routing(uint8_t version_threshold, uint8_t thread_ver)
|
||||
{
|
||||
|
||||
if (thread_ver >= version_threshold + 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void thread_router_bootstrap_pbbr_aloc_generate(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Check if network data changed or bbr info and send proactive an if needed
|
||||
uint8_t bbr_anycast_addr[16];
|
||||
uint8_t bbr_rloc_addr[16];
|
||||
|
||||
thread_addr_write_mesh_local_16(bbr_anycast_addr, 0xfc38, cur->thread_info);
|
||||
addr_delete_matching(cur, bbr_anycast_addr, 128, ADDR_SOURCE_THREAD_ALOC);
|
||||
|
||||
if (0 != thread_common_primary_bbr_get(cur, bbr_rloc_addr, NULL, NULL, NULL)) {
|
||||
// Primary BBR not present
|
||||
return;
|
||||
}
|
||||
if (!addr_get_entry(cur, bbr_rloc_addr)) {
|
||||
// Not our address
|
||||
return;
|
||||
}
|
||||
tr_debug("generate primary BBR anycast address %s", trace_ipv6(bbr_anycast_addr));
|
||||
addr_add(cur, bbr_anycast_addr, 64, ADDR_SOURCE_THREAD_ALOC, 0xffffffff, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
static bool thread_router_bootstrap_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
link_configuration_s *link_conf_ptr = thread_management_configuration_get(cur->id);
|
||||
|
||||
if (!link_conf_ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (thread_info(cur)->version < THREAD_VERSION_1_2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// VR check
|
||||
if (!(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED)) {
|
||||
uint8_t vr_threshold = link_conf_ptr->securityPolicyExt & THREAD_SECURITY_POLICY_VR_VALUE;
|
||||
if (!thread_router_bootstrap_is_version_high_for_routing(vr_threshold, cur->thread_info->version)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(link_conf_ptr->securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED)) {
|
||||
// ccm network
|
||||
if (link_conf_ptr->securityPolicyExt & THREAD_SECURITY_POLICY_NCR_DISABLED) {
|
||||
// NCR bit '1' Non-CCM Routers disabled
|
||||
if (!thread_info(cur)->ccm_credentials_ptr) {
|
||||
// Device does not have domain certificate
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
#define thread_router_bootstrap_pbbr_aloc_generate(cur)
|
||||
#endif
|
||||
|
||||
|
||||
bool thread_router_bootstrap_router_downgrade(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
@ -2239,7 +2315,7 @@ bool thread_router_bootstrap_reed_upgrade(protocol_interface_info_entry_t *cur)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!thread_extension_is_reed_upgrade_allowed(cur)) {
|
||||
if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2699,7 +2775,7 @@ void thread_router_bootstrap_anycast_address_register(protocol_interface_info_en
|
|||
thread_bootstrap_dhcp_anycast_address_generate(cur);
|
||||
thread_bootstrap_service_anycast_address_generate(cur);
|
||||
thread_router_bootstrap_commissioner_aloc_generate(cur);
|
||||
thread_extension_aloc_generate(cur);
|
||||
thread_router_bootstrap_pbbr_aloc_generate(cur);
|
||||
}
|
||||
|
||||
static int thread_router_bootstrap_network_data_propagation(protocol_interface_info_entry_t *cur, uint8_t *childUnicastAddress, bool fullList)
|
||||
|
@ -2802,7 +2878,7 @@ bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entr
|
|||
return true;
|
||||
}
|
||||
|
||||
return !(!thread_extension_version_check(cur->thread_info->version) && !(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED));
|
||||
return !(thread_info(cur)->version < THREAD_VERSION_1_2 && !(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED));
|
||||
}
|
||||
|
||||
void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur)
|
||||
|
|
|
@ -48,9 +48,9 @@
|
|||
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_discovery.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
|
||||
#include "6LoWPAN/Thread/thread_extension_bbr.h"
|
||||
#include "6LoWPAN/Thread/thread_neighbor_class.h"
|
||||
#include "6LoWPAN/Thread/thread_bbr_commercial.h"
|
||||
#include "6LoWPAN/Thread/thread_ccm.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "thread_meshcop_lib.h"
|
||||
#include "thread_diagcop_lib.h"
|
||||
|
@ -645,7 +645,7 @@ int thread_test_pbbr_response_override_set(int8_t interface_id, uint8_t dua_stat
|
|||
{
|
||||
#ifdef HAVE_THREAD
|
||||
(void)interface_id;
|
||||
thread_extension_bbr_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
thread_bbr_commercial_status_override_set(dua_status, dua_count, ba_failure_count);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
@ -1400,7 +1400,7 @@ int thread_test_extension_name_set(int8_t interface_id, char extension_name[16])
|
|||
return -1;
|
||||
}
|
||||
|
||||
return thread_extension_bootstrap_thread_name_set(cur, extension_name);
|
||||
return thread_ccm_thread_name_set(cur, extension_name);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,14 @@
|
|||
#define TMFCOP_TLV_ND_DATA 9
|
||||
#define TMFCOP_TLV_NETWORK_DATA 10
|
||||
|
||||
/* Thread 1.2 defines*/
|
||||
#define TMFCOP_TLV_TIMEOUT 11
|
||||
#define TMFCOP_TLV_NETWORK_NAME 12
|
||||
#define TMFCOP_TLV_SEQUENCE_NUMBER 13
|
||||
#define TMFCOP_TLV_IPV6_ADDRESS 14
|
||||
#define TMFCOP_TLV_COMMISSIONER_SESSION_ID 15
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Write array TLV.
|
||||
|
|
|
@ -239,6 +239,10 @@ static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 1
|
|||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
// Send NA only if it is enabled for the backhaul
|
||||
if (!cur->send_na) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
|
||||
protocol_push(buffer);
|
||||
|
@ -306,7 +310,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
|
||||
if (!protocol_6lowpan_rpl_root_dodag) {
|
||||
// Failed to start
|
||||
tr_info("BBR failed to start");
|
||||
tr_err("BBR failed to start");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -315,7 +319,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
*/
|
||||
if (protocol_interface_address_compare(current_dodag_id) != 0) {
|
||||
//DODAGID is lost need to restart
|
||||
tr_err("DODAGID lost restart RPL");
|
||||
tr_warn("DODAGID lost restart RPL");
|
||||
memset(current_dodag_id, 0, 16);
|
||||
ws_bbr_rpl_root_stop();
|
||||
return;
|
||||
|
@ -507,6 +511,10 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
|
|||
}
|
||||
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, prefix_ptr, &result);
|
||||
if (result > 0) {
|
||||
// remove the Border router from the PAN size
|
||||
result--;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -664,7 +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 params");
|
||||
//tr_debug("ws_etx_read not valid params");
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
@ -900,7 +900,6 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
|
|||
// if in active scan state
|
||||
if (!ws_bootstrap_state_discovery(cur)) {
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
tr_debug("Wrong PAN id r:%u own:%u", data->SrcPANId, cur->ws_info->network_pan_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -962,7 +961,7 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
|
|||
// If pan cost is the same then we select the one we hear highest
|
||||
if (current_pan_cost == pan_cost &&
|
||||
cur->ws_info->parent_info.signal_dbm > data->signal_dbm) {
|
||||
tr_info("EAPOL target dropped Lower link quality %u < %u current", data->signal_dbm, cur->ws_info->parent_info.signal_dbm);
|
||||
tr_info("EAPOL target dropped Lower link quality %d < %d current", data->signal_dbm, cur->ws_info->parent_info.signal_dbm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -998,7 +997,7 @@ parent_selected:
|
|||
uint8_t ll_address[16];
|
||||
ws_bootsrap_create_ll_address(ll_address, neighbor_info.neighbor->mac64);
|
||||
|
||||
if (rpl_control_is_dodag_parent(cur, ll_address, true)) {
|
||||
if (rpl_control_is_dodag_parent(cur, ll_address)) {
|
||||
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;
|
||||
|
@ -1036,7 +1035,6 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
uint8_t *gtkhash_ptr;
|
||||
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
tr_debug("Wrong PAN id r:%u own:%u", data->SrcPANId, cur->ws_info->network_pan_id);
|
||||
return;
|
||||
}
|
||||
ws_bt_ie_t ws_bt_ie;
|
||||
|
@ -1158,7 +1156,6 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us)
|
||||
{
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
tr_debug("Wrong PAN id r:%u own:%u", data->SrcPANId, cur->ws_info->network_pan_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1363,7 +1360,7 @@ 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, true)) {
|
||||
if (rpl_control_is_dodag_parent(interface, ll_target)) {
|
||||
// Possible parent is limited to 3 by default?
|
||||
continue;
|
||||
}
|
||||
|
@ -1498,8 +1495,19 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8_t ll_address[16];
|
||||
|
||||
if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT) {
|
||||
|
||||
ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64);
|
||||
|
||||
if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) {
|
||||
if (!ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64)) {
|
||||
//NUD Not needed for if neighbour is not child or parent candidate
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT * 1.5) {
|
||||
activate_nud = true;
|
||||
} else {
|
||||
|
@ -1518,19 +1526,10 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
|
|||
//Accept quick Probe for init ETX
|
||||
activate_nud = true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64);
|
||||
if (!rpl_control_is_dodag_parent_candidate(cur, ll_address, WS_NEIGHBOUR_MAX_CANDIDATE_PROBE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples;
|
||||
|
@ -2662,7 +2661,7 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t
|
|||
if (cur->ws_info->trickle_pcs_running &&
|
||||
trickle_timer(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery, ticks)) {
|
||||
// send PAN Configuration solicit
|
||||
if (cur->ws_info->pas_requests > PCS_MAX) {
|
||||
if (cur->ws_info->pas_requests >= PCS_MAX) {
|
||||
// if MAX PCS sent restart discovery
|
||||
|
||||
// Remove network keys from MAC
|
||||
|
|
|
@ -161,6 +161,16 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur)
|
|||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_IN) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8651;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8651;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9022;
|
||||
|
@ -228,6 +238,12 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
|
|||
} else if (operating_class == 4) {
|
||||
return 27;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_IN) {
|
||||
if (operating_class == 1) {
|
||||
return 19;
|
||||
} else if (operating_class == 2) {
|
||||
return 10;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
|
|
|
@ -191,6 +191,7 @@ typedef struct ws_bs_ie {
|
|||
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
|
||||
|
||||
#define WS_NEIGBOR_ETX_SAMPLE_MAX 3
|
||||
#define WS_NEIGHBOUR_MAX_CANDIDATE_PROBE 5
|
||||
|
||||
#define WS_PROBE_INIT_BASE_SECONDS 8
|
||||
|
||||
|
|
|
@ -40,6 +40,15 @@ int ws_management_node_init(
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_network_name_set(
|
||||
int8_t interface_id,
|
||||
char *network_name_ptr)
|
||||
{
|
||||
(void)interface_id;
|
||||
(void)network_name_ptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_regulatory_domain_set(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
|
|
|
@ -551,11 +551,12 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
if (ws_wh_ea_read(ie_ext->headerIeList, ie_ext->headerIeListLength, auth_eui64)) {
|
||||
ws_pae_controller_border_router_addr_write(base->interface_ptr, auth_eui64);
|
||||
}
|
||||
if (bs_ie_inline) {
|
||||
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//Update BS if it is part of message
|
||||
if (bs_ie_inline) {
|
||||
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
||||
}
|
||||
|
||||
//Update BT if it is part of message
|
||||
ws_bt_ie_t ws_bt;
|
||||
|
@ -569,12 +570,14 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
}
|
||||
}
|
||||
|
||||
//Refresh Neighbor ETX if unicast
|
||||
if (ws_utt.message_type == WS_FT_DATA && data->DstAddrMode == ADDR_802_15_4_LONG) {
|
||||
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) {
|
||||
|
||||
if (data->DstAddrMode == ADDR_802_15_4_LONG) {
|
||||
neighbor_info.ws_neighbor->unicast_data_rx = true;
|
||||
}
|
||||
|
||||
//Refresh ETX dbm
|
||||
etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index);
|
||||
// Calculate RSL for all UDATA packages heard
|
||||
ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm);
|
||||
|
||||
|
|
|
@ -56,6 +56,31 @@ int ws_management_node_init(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_network_name_set(
|
||||
int8_t interface_id,
|
||||
char *network_name_ptr)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (!network_name_ptr || strlen(network_name_ptr) == 0 || strlen(network_name_ptr) > 32) {
|
||||
return -2;
|
||||
}
|
||||
if (strcmp(cur->ws_info->network_name, network_name_ptr) == 0) {
|
||||
// Network name is the same no further actions required.
|
||||
return 0;
|
||||
}
|
||||
strncpy(cur->ws_info->network_name, network_name_ptr, 32);
|
||||
// if settings change reset_restart for the settings needed
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
// bootstrap active need to restart
|
||||
ws_bootstrap_restart(interface_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int ws_management_regulatory_domain_set(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
|
|
|
@ -863,9 +863,15 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
|||
// 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;
|
||||
|
||||
kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type);
|
||||
if (api != NULL) {
|
||||
if (next_type != IEEE_802_11_GKH) {
|
||||
tr_info("KMP already ongoing; ignored, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||
return;
|
||||
}
|
||||
// Delete KMP
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, api);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
#define WAIT_FOR_REAUTHENTICATION_TICKS 120 * 10 // 120 seconds
|
||||
|
||||
// How many times in maximum stored keys are used for authentication
|
||||
#define STORED_KEYS_MAXIMUM_USE_COUNT 2
|
||||
#define STORED_KEYS_MAXIMUM_USE_COUNT 1
|
||||
|
||||
// Delay for sending the initial EAPOL-Key
|
||||
#define INITIAL_KEY_TIMER_MIN 3
|
||||
|
@ -155,6 +155,17 @@ static const char *KEYS_FILE = KEYS_FILE_NAME;
|
|||
static int8_t tasklet_id = -1;
|
||||
static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link);
|
||||
|
||||
static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address)
|
||||
{
|
||||
if (address) {
|
||||
// Sets target address in use
|
||||
pae_supp->entry.addr = *address;
|
||||
pae_supp->entry_address_active = true;
|
||||
} else {
|
||||
pae_supp->entry_address_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
|
@ -186,8 +197,7 @@ 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 = pae_supp->target_addr;
|
||||
pae_supp->entry_address_active = true;
|
||||
ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr);
|
||||
|
||||
pae_supp->auth_requested = true;
|
||||
|
||||
|
@ -447,7 +457,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 = pae_supp->target_addr;
|
||||
ws_pae_supp_address_set(pae_supp, &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);
|
||||
|
@ -744,7 +754,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
|
|||
|
||||
tr_debug("PAE idle");
|
||||
// Sets target/parent address to null
|
||||
pae_supp->entry_address_active = false;
|
||||
ws_pae_supp_address_set(pae_supp, NULL);
|
||||
// If not already completed, restart bootstrap
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
|
||||
|
|
|
@ -42,8 +42,10 @@ typedef enum {
|
|||
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 DEFAULT_HEAP_PERCENTAGE_THRESHOLD_HIGH 95
|
||||
#define DEFAULT_HEAP_PERCENTAGE_THRESHOLD_CRITICAL 99
|
||||
|
||||
#define SET_WATERMARK(SECTOR_SIZE, THRESHOLD) (SECTOR_SIZE * THRESHOLD / 100)
|
||||
|
||||
#define NS_MAINTENANCE_TIMER_INTERVAL 10 // Maintenance interval
|
||||
|
||||
|
@ -139,8 +141,14 @@ int ns_monitor_init(void)
|
|||
|
||||
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->heap_high_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
DEFAULT_HEAP_PERCENTAGE_THRESHOLD_HIGH
|
||||
);
|
||||
ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
DEFAULT_HEAP_PERCENTAGE_THRESHOLD_CRITICAL
|
||||
);
|
||||
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;
|
||||
|
@ -164,8 +172,14 @@ int ns_monitor_clear(void)
|
|||
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;
|
||||
ns_monitor_ptr->heap_high_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
percentage_high
|
||||
);
|
||||
ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK(
|
||||
ns_monitor_ptr->mem_stats->heap_sector_size,
|
||||
percentage_critical
|
||||
);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -451,7 +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");
|
||||
tr_info("DHCP renew send OK");
|
||||
}
|
||||
|
||||
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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 MAC_DATA_BUFFER_H_
|
||||
#define MAC_DATA_BUFFER_H_
|
||||
|
||||
#include "mac_mcps.h"
|
||||
|
||||
/**
|
||||
* @brief struct mac_aux_security_header_t MAC auxiliarity security header structure
|
||||
* INTERNAL use only
|
||||
*/
|
||||
typedef struct mac_aux_security_header_s {
|
||||
uint32_t frameCounter;
|
||||
uint8_t Keysource[8];
|
||||
uint8_t KeyIndex;
|
||||
unsigned securityLevel: 3;
|
||||
unsigned KeyIdMode: 2;
|
||||
} mac_aux_security_header_t;
|
||||
|
||||
typedef struct mac_fcf_sequence_s {
|
||||
unsigned frametype: 3;
|
||||
bool securityEnabled: 1;
|
||||
bool framePending : 1;
|
||||
bool ackRequested: 1;
|
||||
bool intraPan: 1;
|
||||
bool sequenceNumberSuppress: 1;
|
||||
bool informationElementsPresets: 1;
|
||||
bool DstPanPresents: 1;
|
||||
bool SrcPanPresents: 1;
|
||||
unsigned DstAddrMode: 2; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
|
||||
unsigned frameVersion: 2;
|
||||
unsigned SrcAddrMode: 2; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
|
||||
uint8_t DSN;
|
||||
} mac_fcf_sequence_t;
|
||||
|
||||
typedef struct mac_pre_parsed_frame_s {
|
||||
void *mac_class_ptr;
|
||||
uint8_t *payloadsIePtr;
|
||||
uint8_t *headerIePtr;
|
||||
uint8_t *macPayloadPtr;
|
||||
mlme_device_descriptor_t *neigh_info;
|
||||
uint32_t timestamp;
|
||||
mac_fcf_sequence_t fcf_dsn;
|
||||
uint16_t frameLength; //Encoded or open payload length
|
||||
uint16_t payloadsIeLength;
|
||||
uint16_t headerIeLength;
|
||||
uint16_t mac_header_length;
|
||||
uint16_t header_ie_length;
|
||||
uint16_t mac_payload_length;
|
||||
uint8_t security_aux_header_length;
|
||||
uint8_t LQI;
|
||||
int8_t dbm;
|
||||
bool ack_pendinfg_status;
|
||||
uint8_t buf[]; /*!< Trailing buffer data */
|
||||
} mac_pre_parsed_frame_t;
|
||||
|
||||
typedef struct mac_pre_build_frame {
|
||||
mac_fcf_sequence_t fcf_dsn;
|
||||
uint16_t DstPANId;
|
||||
uint8_t DstAddr[8];
|
||||
uint16_t SrcPANId;
|
||||
uint8_t SrcAddr[8];
|
||||
mac_aux_security_header_t aux_header;
|
||||
uint8_t mac_command_id; //For MLME
|
||||
uint16_t payloadsIeLength;
|
||||
uint16_t headerIeLength;
|
||||
uint16_t mac_payload_length;
|
||||
uint16_t mac_header_length_with_security;
|
||||
uint8_t msduHandle;
|
||||
uint16_t buffer_ttl;
|
||||
struct mcps_data_req_ie_list ie_elements;
|
||||
struct channel_list_s asynch_channel_list;
|
||||
uint8_t *mac_payload;
|
||||
uint8_t status;
|
||||
uint8_t asynch_channel;
|
||||
uint8_t csma_periods_left;
|
||||
uint8_t fhss_retry_count;
|
||||
uint8_t fhss_cca_retry_count;
|
||||
uint32_t tx_time;
|
||||
bool upper_layer_request: 1;
|
||||
bool mac_allocated_payload_ptr: 1;
|
||||
bool asynch_request: 1;
|
||||
bool message_builded: 1;
|
||||
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
|
||||
unsigned priority: 2;
|
||||
struct mac_pre_build_frame *next; //Pointer for queue purpose
|
||||
} mac_pre_build_frame_t;
|
||||
|
||||
|
||||
#endif /* MAC_DATA_BUFFER_H_ */
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "eventOS_event.h"
|
||||
#include "mlme.h"
|
||||
#include "mac_data_buffer.h"
|
||||
#include "ns_list.h"
|
||||
|
||||
struct cca_structure_s;
|
||||
|
@ -186,6 +187,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
bool macBroadcastDisabled: 1;
|
||||
bool scan_active: 1;
|
||||
bool rf_csma_extension_supported: 1;
|
||||
bool ack_tx_possible: 1;
|
||||
/* CSMA Params */
|
||||
unsigned macMinBE: 4;
|
||||
unsigned macMaxBE: 4;
|
||||
|
@ -224,6 +226,8 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
uint16_t multi_cca_interval; /**< Length of the additional CSMA-CA period(s) in microseconds */
|
||||
/* Indirect queue parameters */
|
||||
struct mac_pre_build_frame *indirect_pd_data_request_queue;
|
||||
struct mac_pre_build_frame enhanced_ack_buffer;
|
||||
uint32_t enhanced_ack_handler_timestamp;
|
||||
arm_event_t mac_mcps_timer_event;
|
||||
uint16_t indirect_pending_bytes;
|
||||
arm_nwk_mlme_event_type_e mac_mlme_event;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "mac_filter_api.h"
|
||||
#include "mac_filter.h"
|
||||
#include "mac_common_defines.h"
|
||||
|
||||
#include "mac_defines.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
||||
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
|
||||
|
|
|
@ -74,7 +74,7 @@ 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;
|
||||
static ns_mem_heap_size_t ns_dyn_mem_rate_limiting_threshold = 0xFFFFFFFF;
|
||||
|
||||
/**
|
||||
* Get PHY time stamp.
|
||||
|
@ -83,7 +83,7 @@ static uint32_t ns_dyn_mem_rate_limiting_threshold = 0xFFFFFFFF;
|
|||
* \return Timestamp from PHY
|
||||
*
|
||||
*/
|
||||
static uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||
uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||
{
|
||||
uint32_t timestamp;
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)×tamp);
|
||||
|
@ -1589,15 +1589,12 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload)
|
||||
int8_t mcps_generic_ack_data_request_init(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload)
|
||||
{
|
||||
phy_device_driver_s *dev_driver = rf_ptr->dev_driver->phy_driver;
|
||||
dev_driver_tx_buffer_s *tx_buf = &rf_ptr->dev_driver_tx_buffer;
|
||||
mac_pre_build_frame_t *buffer = &rf_ptr->enhanced_ack_buffer;
|
||||
//save timestamp
|
||||
rf_ptr->enhanced_ack_handler_timestamp = mac_mcps_sap_get_phy_timestamp(rf_ptr);
|
||||
|
||||
ccm_globals_t ccm_ptr;
|
||||
|
||||
mac_pre_build_frame_t pd_act_buf;
|
||||
mac_pre_build_frame_t *buffer = &pd_act_buf;
|
||||
memset(buffer, 0, sizeof(mac_pre_build_frame_t));
|
||||
buffer->fcf_dsn.frametype = FC_ACK_FRAME;
|
||||
buffer->fcf_dsn.frameVersion = fcf->frameVersion;
|
||||
|
@ -1609,6 +1606,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
|
|||
buffer->fcf_dsn.SrcAddrMode = fcf->DstAddrMode;
|
||||
buffer->fcf_dsn.SrcPanPresents = fcf->SrcPanPresents;
|
||||
buffer->fcf_dsn.DstAddrMode = fcf->SrcAddrMode;
|
||||
|
||||
if (buffer->fcf_dsn.sequenceNumberSuppress) {
|
||||
buffer->mac_header_length_with_security = 2;
|
||||
} else {
|
||||
|
@ -1642,8 +1640,6 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
|
|||
|
||||
}
|
||||
|
||||
|
||||
//TODO Request Application data to ACK
|
||||
uint16_t ie_header_length = 0;
|
||||
uint16_t ie_payload_length = 0;
|
||||
|
||||
|
@ -1666,15 +1662,31 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
|
|||
|
||||
//This will prepare MHR length with Header IE
|
||||
mac_header_information_elements_preparation(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool init_build)
|
||||
{
|
||||
phy_device_driver_s *dev_driver = rf_ptr->dev_driver->phy_driver;
|
||||
dev_driver_tx_buffer_s *tx_buf = &rf_ptr->dev_driver_tx_buffer;
|
||||
|
||||
ccm_globals_t ccm_ptr;
|
||||
mac_pre_build_frame_t *buffer = &rf_ptr->enhanced_ack_buffer;
|
||||
|
||||
|
||||
if (buffer->fcf_dsn.securityEnabled) {
|
||||
//Remember to update security counter here!
|
||||
buffer->aux_header.frameCounter = mac_mlme_framecounter_get(rf_ptr);
|
||||
if (init_build) {
|
||||
buffer->aux_header.frameCounter = mac_mlme_framecounter_get(rf_ptr);
|
||||
}
|
||||
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer)) {
|
||||
return -2;
|
||||
}
|
||||
//Increment security counter
|
||||
mac_mlme_framecounter_increment(rf_ptr);
|
||||
if (init_build) {
|
||||
//Increment security counter
|
||||
mac_mlme_framecounter_increment(rf_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate Payload length here with IE extension
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
|
||||
#include "mlme.h"
|
||||
#include "mac_common_defines.h"
|
||||
#include "mac_data_buffer.h"
|
||||
|
||||
struct protocol_interface_rf_mac_setup;
|
||||
struct mcps_data_req_s;
|
||||
struct arm_phy_sap_msg_s;
|
||||
struct mcps_purge_s;
|
||||
struct mcps_data_ie_list;
|
||||
struct mcps_data_req_ie_list;
|
||||
struct channel_list_s;
|
||||
|
||||
|
@ -62,88 +62,6 @@ typedef enum {
|
|||
// Interval between two CCA checks
|
||||
#define MAC_DEFAULT_CSMA_MULTI_CCA_INTERVAL 1000
|
||||
|
||||
/**
|
||||
* @brief struct mac_aux_security_header_t MAC auxiliarity security header structure
|
||||
* INTERNAL use only
|
||||
*/
|
||||
typedef struct mac_aux_security_header_s {
|
||||
unsigned securityLevel: 3;
|
||||
unsigned KeyIdMode: 2;
|
||||
uint32_t frameCounter;
|
||||
uint8_t Keysource[8];
|
||||
uint8_t KeyIndex;
|
||||
} mac_aux_security_header_t;
|
||||
|
||||
typedef struct mac_fcf_sequence_s {
|
||||
unsigned frametype: 3;
|
||||
bool securityEnabled: 1;
|
||||
bool framePending : 1;
|
||||
bool ackRequested: 1;
|
||||
bool intraPan: 1;
|
||||
bool sequenceNumberSuppress: 1;
|
||||
bool informationElementsPresets: 1;
|
||||
bool DstPanPresents: 1;
|
||||
bool SrcPanPresents: 1;
|
||||
unsigned DstAddrMode: 2; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
|
||||
unsigned frameVersion: 2;
|
||||
unsigned SrcAddrMode: 2; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
|
||||
uint8_t DSN;
|
||||
} mac_fcf_sequence_t;
|
||||
|
||||
typedef struct mac_pre_parsed_frame_s {
|
||||
void *mac_class_ptr;
|
||||
uint8_t *payloadsIePtr;
|
||||
uint8_t *headerIePtr;
|
||||
uint8_t *macPayloadPtr;
|
||||
mlme_device_descriptor_t *neigh_info;
|
||||
uint8_t LQI;
|
||||
int8_t dbm;
|
||||
mac_fcf_sequence_t fcf_dsn;
|
||||
uint16_t frameLength; //Encoded or open payload length
|
||||
uint16_t payloadsIeLength;
|
||||
uint16_t headerIeLength;
|
||||
uint16_t mac_header_length;
|
||||
uint16_t header_ie_length;
|
||||
uint8_t security_aux_header_length;
|
||||
uint16_t mac_payload_length;
|
||||
uint32_t timestamp;
|
||||
bool ack_pendinfg_status;
|
||||
|
||||
uint8_t buf[]; /*!< Trailing buffer data */
|
||||
} mac_pre_parsed_frame_t;
|
||||
|
||||
typedef struct mac_pre_build_frame {
|
||||
mac_fcf_sequence_t fcf_dsn;
|
||||
uint16_t DstPANId;
|
||||
uint8_t DstAddr[8];
|
||||
uint16_t SrcPANId;
|
||||
uint8_t SrcAddr[8];
|
||||
mac_aux_security_header_t aux_header;
|
||||
uint8_t mac_command_id; //For MLME
|
||||
uint16_t payloadsIeLength;
|
||||
uint16_t headerIeLength;
|
||||
uint16_t mac_payload_length;
|
||||
uint16_t mac_header_length_with_security;
|
||||
uint8_t msduHandle;
|
||||
uint16_t buffer_ttl;
|
||||
struct mcps_data_req_ie_list ie_elements;
|
||||
struct channel_list_s asynch_channel_list;
|
||||
uint8_t *mac_payload;
|
||||
uint8_t status;
|
||||
uint8_t asynch_channel;
|
||||
uint8_t csma_periods_left;
|
||||
uint8_t fhss_retry_count;
|
||||
uint8_t fhss_cca_retry_count;
|
||||
uint32_t tx_time;
|
||||
bool upper_layer_request;
|
||||
bool mac_allocated_payload_ptr: 1;
|
||||
bool asynch_request: 1;
|
||||
bool message_builded: 1;
|
||||
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
|
||||
unsigned priority: 2;
|
||||
struct mac_pre_build_frame *next; //Pointer for queue purpose
|
||||
} mac_pre_build_frame_t;
|
||||
|
||||
|
||||
void mac_generic_event_trig(uint8_t event_type, void *mac_ptr, bool low_latency);
|
||||
|
||||
|
@ -214,8 +132,12 @@ uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_ma
|
|||
|
||||
int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);
|
||||
|
||||
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);
|
||||
int8_t mcps_generic_ack_data_request_init(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);
|
||||
|
||||
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, bool init_build);
|
||||
|
||||
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
|
||||
|
||||
uint32_t mac_mcps_sap_get_phy_timestamp(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
||||
|
||||
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */
|
||||
|
|
|
@ -738,7 +738,7 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
|||
if (!set_req || !rf_mac_setup || !rf_mac_setup->dev_driver || !rf_mac_setup->dev_driver->phy_driver) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *pu8 = NULL;
|
||||
switch (set_req->attr) {
|
||||
case macAckWaitDuration:
|
||||
return mac_mlme_set_ack_wait_duration(rf_mac_setup, set_req);
|
||||
|
@ -758,11 +758,29 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
|||
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
|
||||
}
|
||||
return 0;
|
||||
case macTXPower:
|
||||
pu8 = (uint8_t *) set_req->value_pointer;
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_TX_POWER, pu8);
|
||||
tr_debug("Set TX output power to %u%%", *pu8);
|
||||
return 0;
|
||||
case macCCAThreshold:
|
||||
pu8 = (uint8_t *) set_req->value_pointer;
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CCA_THRESHOLD, pu8);
|
||||
tr_debug("Set CCA threshold to %u%%", *pu8);
|
||||
return 0;
|
||||
case macMultiCSMAParameters:
|
||||
return mac_mlme_set_multi_csma_parameters(rf_mac_setup, set_req);
|
||||
case macRfConfiguration:
|
||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_RF_CONFIGURATION, (uint8_t *) set_req->value_pointer);
|
||||
mac_mlme_set_symbol_rate(rf_mac_setup);
|
||||
phy_rf_channel_configuration_s *config_params = (phy_rf_channel_configuration_s *)set_req->value_pointer;
|
||||
tr_info("RF config update:");
|
||||
tr_info("Frequency(ch0): %"PRIu32"Hz", config_params->channel_0_center_frequency);
|
||||
tr_info("Channel spacing: %"PRIu32"Hz", config_params->channel_spacing);
|
||||
tr_info("Datarate: %"PRIu32"bps", config_params->datarate);
|
||||
tr_info("Number of channels: %u", config_params->number_of_channels);
|
||||
tr_info("Modulation: %u", config_params->modulation);
|
||||
tr_info("Modulation index: %u", config_params->modulation_index);
|
||||
return 0;
|
||||
default:
|
||||
return mac_mlme_handle_set_values(rf_mac_setup, set_req);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "MAC/IEEE802_15_4/mac_defines.h"
|
||||
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
|
||||
#include "MAC/IEEE802_15_4/mac_timer.h"
|
||||
#include "MAC/IEEE802_15_4/mac_security_mib.h"
|
||||
#include "MAC/IEEE802_15_4/mac_mlme.h"
|
||||
#include "MAC/IEEE802_15_4/mac_filter.h"
|
||||
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
||||
|
@ -409,6 +410,28 @@ static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
|
||||
{
|
||||
rf_ptr->mac_ack_tx_active = false;
|
||||
if (rf_ptr->fhss_api) {
|
||||
//SET tx completed false because ack isnot never queued
|
||||
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff);
|
||||
}
|
||||
if (rf_ptr->active_pd_data_request) {
|
||||
|
||||
if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) {
|
||||
uint32_t current_counter = mac_mlme_framecounter_get(rf_ptr);
|
||||
if (mac_data_counter_too_small(current_counter, rf_ptr->active_pd_data_request->aux_header.frameCounter)) {
|
||||
rf_ptr->active_pd_data_request->aux_header.frameCounter = current_counter;
|
||||
mac_mlme_framecounter_increment(rf_ptr);
|
||||
}
|
||||
}
|
||||
//GEN TX failure
|
||||
mac_sap_cca_fail_cb(rf_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
|
||||
{
|
||||
|
||||
|
@ -419,7 +442,17 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
if (status == PHY_LINK_CCA_PREPARE) {
|
||||
|
||||
if (rf_ptr->mac_ack_tx_active) {
|
||||
return PHY_TX_ALLOWED;
|
||||
//Accept direct non crypted acks and crypted only if neighbor is at list
|
||||
if (rf_ptr->ack_tx_possible || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode)) {
|
||||
return PHY_TX_ALLOWED;
|
||||
}
|
||||
|
||||
//Compare time to started time
|
||||
if (mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->enhanced_ack_handler_timestamp > ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US || mcps_generic_ack_build(rf_ptr, false) != 0) {
|
||||
mac_data_ack_tx_finish(rf_ptr);
|
||||
}
|
||||
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
|
||||
|
@ -467,23 +500,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
|
||||
|
||||
if (rf_ptr->mac_ack_tx_active) {
|
||||
rf_ptr->mac_ack_tx_active = false;
|
||||
if (rf_ptr->fhss_api) {
|
||||
//SET tx completed false because ack isnot never queued
|
||||
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff);
|
||||
}
|
||||
if (rf_ptr->active_pd_data_request) {
|
||||
|
||||
if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) {
|
||||
uint32_t current_counter = mac_mlme_framecounter_get(rf_ptr);
|
||||
if (mac_data_counter_too_small(current_counter, rf_ptr->active_pd_data_request->aux_header.frameCounter)) {
|
||||
rf_ptr->active_pd_data_request->aux_header.frameCounter = current_counter;
|
||||
mac_mlme_framecounter_increment(rf_ptr);
|
||||
}
|
||||
}
|
||||
//GEN TX failure
|
||||
mac_sap_cca_fail_cb(rf_ptr);
|
||||
}
|
||||
mac_data_ack_tx_finish(rf_ptr);
|
||||
return 0;
|
||||
} else {
|
||||
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
|
||||
|
@ -765,7 +782,17 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
|
|||
mac_api->enhanced_ack_data_req_cb(mac_api, &ack_payload, pd_data_ind->dbm, pd_data_ind->link_quality);
|
||||
//Calculate Delta time
|
||||
|
||||
return mcps_generic_ack_build(rf_ptr, fcf_read, pd_data_ind->data_ptr, &ack_payload);
|
||||
if (mcps_generic_ack_data_request_init(rf_ptr, fcf_read, pd_data_ind->data_ptr, &ack_payload) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0 || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode)) {
|
||||
rf_ptr->ack_tx_possible = true;
|
||||
} else {
|
||||
rf_ptr->ack_tx_possible = false;
|
||||
}
|
||||
|
||||
return mcps_generic_ack_build(rf_ptr, true);
|
||||
}
|
||||
|
||||
static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
struct protocol_interface_rf_mac_setup;
|
||||
struct arm_phy_sap_msg_s;
|
||||
|
||||
#define ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US 3500
|
||||
|
||||
/**
|
||||
* Send a buffer to the MAC.
|
||||
|
|
|
@ -700,6 +700,19 @@ void sw_mac_stats_update(protocol_interface_rf_mac_setup_s *setup, mac_stats_typ
|
|||
}
|
||||
}
|
||||
|
||||
int ns_sw_mac_phy_statistics_start(struct mac_api_s *mac_api, phy_rf_statistics_s *phy_statistics)
|
||||
{
|
||||
if (!mac_api || !phy_statistics) {
|
||||
return -1;
|
||||
}
|
||||
protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_mac_api(mac_api);
|
||||
if (!mac_setup) {
|
||||
return -1;
|
||||
}
|
||||
mac_setup->dev_driver->phy_driver->phy_rf_statistics = phy_statistics;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api)
|
||||
{
|
||||
if (!mac_api) {
|
||||
|
|
|
@ -28,7 +28,7 @@ typedef struct eth_mac_internal_s {
|
|||
arm_device_driver_list_s *dev_driver;
|
||||
uint8_t *mtu_ptr;
|
||||
uint16_t mtu_size;
|
||||
uint8_t mac48[6];
|
||||
uint8_t mac48_iid64[8];
|
||||
bool active_data_request;
|
||||
int8_t tasklet_id;
|
||||
//linked list link
|
||||
|
@ -52,6 +52,8 @@ static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb
|
|||
static void data_req(const eth_mac_api_t *api, const eth_data_req_t *data);
|
||||
static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48);
|
||||
static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf);
|
||||
static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64);
|
||||
static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf);
|
||||
|
||||
static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
|
||||
static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
|
||||
|
@ -98,6 +100,7 @@ eth_mac_api_t *ethernet_mac_create(int8_t driver_id)
|
|||
switch (driver->phy_driver->link_type) {
|
||||
|
||||
case PHY_LINK_SLIP:
|
||||
case PHY_LINK_PPP:
|
||||
//Do not Allocate
|
||||
address_resolution_needed = false;
|
||||
buffer_length = 0;
|
||||
|
@ -133,19 +136,29 @@ eth_mac_api_t *ethernet_mac_create(int8_t driver_id)
|
|||
memset(this, 0, sizeof(eth_mac_api_t));
|
||||
this->mac_initialize = ð_mac_api_init;
|
||||
this->data_req = &data_req;
|
||||
this->mac48_get = &mac48_address_get;
|
||||
this->mac48_set = &mac48_address_set;
|
||||
|
||||
if (driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
this->iid64_get = &iid64_address_get;
|
||||
this->iid64_set = &iid64_address_set;
|
||||
} else {
|
||||
this->mac48_get = &mac48_address_get;
|
||||
this->mac48_set = &mac48_address_set;
|
||||
}
|
||||
|
||||
this->address_resolution_needed = address_resolution_needed;
|
||||
|
||||
memset(&mac_store.mac48, 0, 6);
|
||||
memset(&mac_store.mac48_iid64, 0, 8);
|
||||
mac_store.active_data_request = false;
|
||||
mac_store.mac_api = this;
|
||||
mac_store.dev_driver = driver;
|
||||
mac_store.mtu_ptr = buffer_ptr;
|
||||
mac_store.mtu_size = buffer_length;
|
||||
|
||||
memcpy(&mac_store.mac48, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
if (driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
|
||||
} else {
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
}
|
||||
if (mac_store.tasklet_id == -1) {
|
||||
mac_store.tasklet_id = eventOS_event_handler_create(ðernet_mac_tasklet, ETH_INIT_EVENT);
|
||||
}
|
||||
|
@ -289,7 +302,7 @@ static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uin
|
|||
|
||||
data_len -= 4;
|
||||
data_ptr += 4;
|
||||
} else if (driver->phy_driver->link_type == PHY_LINK_SLIP) {
|
||||
} else if (driver->phy_driver->link_type == PHY_LINK_SLIP || driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
data_ind->etehernet_type = ETHERTYPE_IPV6;
|
||||
}
|
||||
|
||||
|
@ -357,10 +370,10 @@ static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48)
|
|||
if (!mac48 || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(mac_store.mac48, mac48, 6);
|
||||
memcpy(mac_store.mac48_iid64, mac48, 6);
|
||||
phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
|
||||
if (driver->address_write) {
|
||||
driver->address_write(PHY_MAC_48BIT, mac_store.mac48);
|
||||
driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -370,7 +383,30 @@ static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf)
|
|||
if (!mac48_buf || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(&mac_store.mac48, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
memcpy(mac48_buf, mac_store.mac48, 6);
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
memcpy(mac48_buf, mac_store.mac48_iid64, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64)
|
||||
{
|
||||
if (!iid64 || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(mac_store.mac48_iid64, iid64, 8);
|
||||
phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
|
||||
if (driver->address_write) {
|
||||
driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf)
|
||||
{
|
||||
if (!iid64_buf || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
|
||||
memcpy(iid64_buf, mac_store.mac48_iid64, 8);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -410,6 +410,7 @@ struct protocol_interface_info_entry {
|
|||
bool mpl_treat_realm_domains_as_one: 1;
|
||||
bool mpl_auto_domain_on_group_join: 1;
|
||||
#endif
|
||||
bool send_na : 1;
|
||||
/* RFC 4861 Router Variables */
|
||||
bool ip_forwarding : 1;
|
||||
bool ip_multicast_forwarding : 1;
|
||||
|
@ -499,6 +500,7 @@ extern uint8_t nwk_bootsrap_ready(protocol_interface_info_entry_t *cur);
|
|||
extern protocol_interface_info_entry_t *protocol_stack_interface_info_get(nwk_interface_id nwk_id);
|
||||
extern bool nwk_interface_compare_mac_address(protocol_interface_info_entry_t *cur, uint_fast8_t addrlen, const uint8_t addr[/*addrlen*/]);
|
||||
extern protocol_interface_info_entry_t *protocol_stack_interface_generate_ethernet(struct eth_mac_api_s *api);
|
||||
extern protocol_interface_info_entry_t *protocol_stack_interface_generate_ppp(struct eth_mac_api_s *api);
|
||||
extern protocol_interface_info_entry_t *protocol_stack_interface_generate_lowpan(struct mac_api_s *api);
|
||||
extern uint32_t protocol_stack_interface_set_reachable_time(protocol_interface_info_entry_t *cur, uint32_t base_reachable_time);
|
||||
extern void net_bootsrap_cb_run(uint8_t event);
|
||||
|
|
|
@ -485,6 +485,7 @@ static void protocol_core_base_finish_init(protocol_interface_info_entry_t *entr
|
|||
entry->dad_failures = 0;
|
||||
entry->icmp_tokens = 10;
|
||||
entry->mle_link_reject_tokens = 2;
|
||||
entry->send_na = true; /* Default to on for now... */
|
||||
entry->ip_forwarding = true; /* Default to on for now... */
|
||||
entry->ip_multicast_forwarding = true; /* Default to on for now... */
|
||||
#ifdef HAVE_IPV6_ND
|
||||
|
@ -868,7 +869,6 @@ protocol_interface_info_entry_t *protocol_stack_interface_generate_ethernet(eth_
|
|||
if (!api) {
|
||||
return NULL;
|
||||
}
|
||||
protocol_interface_info_entry_t *new_entry = NULL;
|
||||
|
||||
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
|
||||
if (cur->eth_mac_api == api) {
|
||||
|
@ -876,32 +876,74 @@ protocol_interface_info_entry_t *protocol_stack_interface_generate_ethernet(eth_
|
|||
}
|
||||
}
|
||||
|
||||
if (api) {
|
||||
new_entry = protocol_core_interface_ethernet_entry_get(api);
|
||||
protocol_interface_info_entry_t *new_entry = protocol_core_interface_ethernet_entry_get(api);
|
||||
|
||||
if (new_entry) {
|
||||
neighbor_cache_init(&(new_entry->neigh_cache));
|
||||
pan_blacklist_cache_init(&(new_entry->pan_blaclist_cache));
|
||||
pan_coordinator_blacklist_cache_init(&(new_entry->pan_cordinator_black_list));
|
||||
ipv6_neighbour_cache_init(&new_entry->ipv6_neighbour_cache, new_entry->id);
|
||||
addr_max_slaac_entries_set(new_entry, 16);
|
||||
uint8_t mac[6];
|
||||
int8_t error = api->mac48_get(api, mac);
|
||||
if (error) {
|
||||
tr_error("mac_ext_mac64_address_get failed: %d", error);
|
||||
ns_dyn_mem_free(new_entry);
|
||||
return NULL;
|
||||
}
|
||||
if (!new_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protocol_stack_interface_iid_eui64_generate(new_entry, mac);
|
||||
ns_list_add_to_start(&protocol_interface_info_list, new_entry);
|
||||
neighbor_cache_init(&(new_entry->neigh_cache));
|
||||
pan_blacklist_cache_init(&(new_entry->pan_blaclist_cache));
|
||||
pan_coordinator_blacklist_cache_init(&(new_entry->pan_cordinator_black_list));
|
||||
ipv6_neighbour_cache_init(&new_entry->ipv6_neighbour_cache, new_entry->id);
|
||||
addr_max_slaac_entries_set(new_entry, 16);
|
||||
uint8_t mac[6];
|
||||
int8_t error = api->mac48_get(api, mac);
|
||||
if (error) {
|
||||
tr_error("mac_ext_mac64_address_get failed: %d", error);
|
||||
ns_dyn_mem_free(new_entry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void) ipv6_route_table_set_max_entries(new_entry->id, ROUTE_RADV, 16);
|
||||
protocol_stack_interface_iid_eui64_generate(new_entry, mac);
|
||||
ns_list_add_to_start(&protocol_interface_info_list, new_entry);
|
||||
|
||||
return new_entry;
|
||||
(void) ipv6_route_table_set_max_entries(new_entry->id, ROUTE_RADV, 16);
|
||||
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
protocol_interface_info_entry_t *protocol_stack_interface_generate_ppp(eth_mac_api_t *api)
|
||||
{
|
||||
if (!api) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
|
||||
if (cur->eth_mac_api == api) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
protocol_interface_info_entry_t *new_entry = protocol_core_interface_ethernet_entry_get(api);
|
||||
|
||||
if (!new_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
neighbor_cache_init(&(new_entry->neigh_cache));
|
||||
pan_blacklist_cache_init(&(new_entry->pan_blaclist_cache));
|
||||
pan_coordinator_blacklist_cache_init(&(new_entry->pan_cordinator_black_list));
|
||||
ipv6_neighbour_cache_init(&new_entry->ipv6_neighbour_cache, new_entry->id);
|
||||
addr_max_slaac_entries_set(new_entry, 16);
|
||||
uint8_t iid64[8];
|
||||
int8_t error = api->iid64_get(api, iid64);
|
||||
if (error) {
|
||||
tr_error("iid64_get failed: %d", error);
|
||||
ns_dyn_mem_free(new_entry);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(new_entry->iid_slaac, iid64, 8);
|
||||
memcpy(new_entry->iid_eui64, iid64, 8);
|
||||
new_entry->send_mld = false; // No mld for PPP
|
||||
new_entry->dup_addr_detect_transmits = 0; // No duplicate detection for PPP
|
||||
new_entry->send_na = false; // No neighbor advertisements for PPP
|
||||
|
||||
ns_list_add_to_start(&protocol_interface_info_list, new_entry);
|
||||
|
||||
(void) ipv6_route_table_set_max_entries(new_entry->id, ROUTE_RADV, 16);
|
||||
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
protocol_interface_info_entry_t *protocol_stack_interface_generate_lowpan(mac_api_t *api)
|
||||
|
|
|
@ -204,20 +204,35 @@ void rpl_control_address_register_done(protocol_interface_info_entry_t *interfac
|
|||
}
|
||||
}
|
||||
|
||||
bool rpl_control_is_dodag_parent(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], bool selected)
|
||||
bool rpl_control_is_dodag_parent(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16])
|
||||
{
|
||||
if (!interface->rpl_domain) {
|
||||
return false;
|
||||
}
|
||||
// go through instances and parents and check if they match the address.
|
||||
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
|
||||
if (rpl_instance_address_is_parent(instance, ll_addr, selected)) {
|
||||
if (rpl_instance_address_is_parent(instance, ll_addr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rpl_control_is_dodag_parent_candidate(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], uint16_t candidate_cmp_limiter)
|
||||
{
|
||||
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_candidate(instance, ll_addr, candidate_cmp_limiter)) {
|
||||
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) {
|
||||
|
|
|
@ -147,7 +147,8 @@ 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]);
|
||||
bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], bool selected);
|
||||
bool rpl_control_is_dodag_parent(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
|
||||
bool rpl_control_is_dodag_parent_candidate(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint16_t candidate_cmp_limiter);
|
||||
uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_entry *interface, bool parent_list);
|
||||
void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
|
||||
/* Parent link confirmation API extension */
|
||||
|
|
|
@ -1617,24 +1617,33 @@ 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 selected)
|
||||
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr)
|
||||
{
|
||||
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
|
||||
if (selected && !neighbour->dodag_parent) {
|
||||
if (!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;
|
||||
}
|
||||
|
||||
bool rpl_instance_address_is_candidate(rpl_instance_t *instance, const uint8_t *ipv6_addr, uint16_t candidate_amount)
|
||||
{
|
||||
uint16_t list_compared = 0;
|
||||
|
||||
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
|
||||
if (addr_ipv6_equal(neighbour->ll_address, ipv6_addr)) {
|
||||
return true;
|
||||
}
|
||||
list_compared++;
|
||||
if (candidate_amount && list_compared >= candidate_amount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
|
@ -1708,6 +1717,14 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks)
|
|||
if (rpl_dodag_am_leaf(dodag) && !instance->poison_count) {
|
||||
return;
|
||||
}
|
||||
// We dont have any valid address in interface
|
||||
if (ns_list_count(&instance->dao_targets) == 0) {
|
||||
return;
|
||||
}
|
||||
/* Address registrations for parent ongoing*/
|
||||
if (rpl_policy_parent_confirmation_requested() && instance->pending_neighbour_confirmation) {
|
||||
return;
|
||||
}
|
||||
/* If we are waiting for DAO or DAO registration is needed we dont send periodic DIOs */
|
||||
if (instance->dao_in_transit || instance->delay_dao_timer > 0) {
|
||||
return;
|
||||
|
|
|
@ -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 selected);
|
||||
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr);
|
||||
bool rpl_instance_address_is_candidate(rpl_instance_t *instance, const uint8_t *ipv6_addr, uint16_t candidate_amount);
|
||||
uint16_t rpl_instance_address_candidate_count(rpl_instance_t *instance, bool selected_parents);
|
||||
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);
|
||||
|
|
|
@ -244,6 +244,9 @@ static int8_t supp_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
|
|||
const uint8_t identity_size = sizeof(identity) - 1;
|
||||
if (data->tls_send.total_len != identity_size) {
|
||||
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, identity_size);
|
||||
if (!data->tls_send.data) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(data->tls_send.data + TLS_HEAD_LEN, identity, identity_size);
|
||||
}
|
||||
flags = 0xff;
|
||||
|
|
|
@ -496,6 +496,9 @@ static int16_t tls_sec_prot_tls_send(void *handle, const void *buf, size_t len)
|
|||
if (!data->tls_send.data) {
|
||||
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, prot->header_size, TLS_SEC_PROT_BUFFER_SIZE);
|
||||
}
|
||||
if (!data->tls_send.data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data->tls_send.data + prot->header_size + data->tls_send.handled_len, buf, len);
|
||||
data->tls_send.handled_len += len;
|
||||
|
|
|
@ -92,19 +92,24 @@ static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t ack
|
|||
entry->stored_diff_etx = entry->etx;
|
||||
}
|
||||
|
||||
|
||||
uint32_t etx = attempts << (12 - ETX_MOVING_AVERAGE_FRACTION);
|
||||
|
||||
if (acks_rx > 1) {
|
||||
if (acks_rx) {
|
||||
etx /= acks_rx;
|
||||
} else {
|
||||
etx = 0xffff;
|
||||
}
|
||||
|
||||
if ((etx_info.max_etx_update) && etx > etx_info.max_etx_update) {
|
||||
etx = etx_info.max_etx_update;
|
||||
}
|
||||
|
||||
//Add old etx 7/8 to new one
|
||||
etx += entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);
|
||||
if (etx_info.cache_sample_requested && entry->etx_samples == 1) {
|
||||
// skip the initial value as RSSI generated ETX is not valid
|
||||
etx = etx << 3;
|
||||
} else {
|
||||
//Add old etx 7/8 to new one
|
||||
etx += entry->etx - (entry->etx >> ETX_MOVING_AVERAGE_FRACTION);
|
||||
}
|
||||
|
||||
if (etx > 0xffff) {
|
||||
etx = 0xffff;
|
||||
|
@ -201,11 +206,12 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
|
|||
entry->etx_samples++;
|
||||
}
|
||||
|
||||
if (etx_info.cache_sample_requested && !entry->tmp_etx) {
|
||||
if (etx_info.cache_sample_requested) {
|
||||
|
||||
etx_sample_storage_t *storage = etx_cache_sample_update(attribute_index, attempts, success);
|
||||
entry->accumulated_failures = 0;
|
||||
if (!etx_update_possible(storage, entry, 0)) {
|
||||
|
||||
if (!entry->etx || (entry->etx_samples > 1 && !etx_update_possible(storage, entry, 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,23 +44,23 @@ void (*fhss_uc_switch)(void) = NULL;
|
|||
void (*fhss_bc_switch)(void) = NULL;
|
||||
#endif /*FHSS_CHANNEL_DEBUG_CBS*/
|
||||
// Seconds to milliseconds
|
||||
#define S_TO_MS(x) (((int32_t)x)*1000)
|
||||
#define S_TO_MS(x) (((int64_t)x)*1000)
|
||||
// Milliseconds to seconds
|
||||
#define MS_TO_S(x) divide_integer(x, 1000)
|
||||
// Seconds to microseconds
|
||||
#define S_TO_US(x) (((int32_t)x)*1000000)
|
||||
#define S_TO_US(x) (((int64_t)x)*1000000)
|
||||
// Microseconds to seconds
|
||||
#define US_TO_S(x) divide_integer(x, 1000000)
|
||||
// Milliseconds to microseconds
|
||||
#define MS_TO_US(x) (((int32_t)x)*1000)
|
||||
#define MS_TO_US(x) (((int64_t)x)*1000)
|
||||
// Microseconds to milliseconds
|
||||
#define US_TO_MS(x) divide_integer(x, 1000)
|
||||
// Milliseconds to nanoseconds
|
||||
#define MS_TO_NS(x) (((int32_t)x)*1000000)
|
||||
#define MS_TO_NS(x) (((int64_t)x)*1000000)
|
||||
// Nanoseconds to milliseconds
|
||||
#define NS_TO_MS(x) divide_integer(x, 1000000)
|
||||
// Microseconds to nanoseconds
|
||||
#define US_TO_NS(x) (((int32_t)x)*1000)
|
||||
#define US_TO_NS(x) (((int64_t)x)*1000)
|
||||
// Nanoseconds to microseconds
|
||||
#define NS_TO_US(x) divide_integer(x, 1000)
|
||||
#define DEF_2E24 0x1000000
|
||||
|
@ -86,8 +86,11 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
|
|||
static uint32_t fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure);
|
||||
|
||||
// This function supports rounding up
|
||||
static int32_t divide_integer(int32_t dividend, int32_t divisor)
|
||||
static int64_t divide_integer(int64_t dividend, int32_t divisor)
|
||||
{
|
||||
if (!divisor) {
|
||||
return dividend;
|
||||
}
|
||||
if (dividend < 0) {
|
||||
return (dividend - divisor / 2) / divisor;
|
||||
}
|
||||
|
@ -854,16 +857,16 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
|
|||
//TODO: Compensation for fixed channel configuration
|
||||
if (SYNCH_COMPENSATION_MIN_INTERVAL <= US_TO_S(time_since_last_synch_us)) {
|
||||
// Update clock drift
|
||||
int32_t drift_per_ms_tmp = divide_integer(MS_TO_NS((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_MS(time_since_last_synch_us));
|
||||
int32_t drift_per_ms_tmp = divide_integer((int32_t)MS_TO_NS((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_MS(time_since_last_synch_us));
|
||||
if (drift_per_ms_tmp > MAX_DRIFT_COMPENSATION_STEP) {
|
||||
drift_per_ms_tmp = MAX_DRIFT_COMPENSATION_STEP;
|
||||
} else if (drift_per_ms_tmp < -MAX_DRIFT_COMPENSATION_STEP) {
|
||||
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));
|
||||
fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, NS_TO_US((int64_t)(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);
|
||||
tr_debug("synch to parent: %s, drift: %"PRIi32"ms in %"PRIu64" 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;
|
||||
|
|
|
@ -17,5 +17,6 @@
|
|||
|
||||
/* Thread feature is active with minimal functionality */
|
||||
#define HAVE_THREAD
|
||||
#define HAVE_THREAD_V2
|
||||
|
||||
#define HAVE_MPL
|
||||
|
|
|
@ -245,6 +245,11 @@ static uint8_t ethernet_llao_write(protocol_interface_info_entry_t *cur, uint8_t
|
|||
{
|
||||
(void) must;
|
||||
(void) ip_addr;
|
||||
|
||||
if (memcmp(cur->mac, ADDR_EUI64_ZERO, 8) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt_out) {
|
||||
opt_out[0] = opt_type;
|
||||
opt_out[1] = 1;
|
||||
|
@ -963,6 +968,10 @@ void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const ui
|
|||
if (cur->ipv6_configure && cur->ipv6_configure->IPv6_ND_state == IPV6_ROUTER_SOLICATION) {
|
||||
cur->ipv6_configure->IPv6_ND_state = IPV6_GP_CONFIG;
|
||||
}
|
||||
// If DAD not enabled address is valid right away
|
||||
if (cur->dup_addr_detect_transmits == 0) {
|
||||
address_entry->cb(cur, address_entry, ADDR_CALLBACK_DAD_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -829,7 +829,7 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
|
|||
if (retval != 0) {
|
||||
tr_warn("dhcp service socket_sendto fails: %i", retval);
|
||||
} else {
|
||||
tr_warn("dhcp service socket_sendto %s", trace_ipv6(msg_tr_ptr->addr.address));
|
||||
tr_debug("dhcp service socket_sendto %s", trace_ipv6(msg_tr_ptr->addr.address));
|
||||
}
|
||||
}
|
||||
bool dhcp_service_timer_tick(uint16_t ticks)
|
||||
|
|
|
@ -701,6 +701,28 @@ int8_t arm_nwk_interface_ethernet_init(eth_mac_api_t *api, const char *interface
|
|||
#endif
|
||||
}
|
||||
|
||||
extern int8_t arm_nwk_interface_ppp_init(struct eth_mac_api_s *api, const char *interface_name_ptr)
|
||||
{
|
||||
#ifdef HAVE_ETHERNET
|
||||
if (!api) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_ppp(api);
|
||||
if (!cur) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
cur->if_up = ipv6_interface_up;
|
||||
cur->if_down = ipv6_interface_down;
|
||||
cur->interface_name = interface_name_ptr;
|
||||
return cur->id;
|
||||
#else
|
||||
(void)api;
|
||||
(void)interface_name_ptr;
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t arm_nwk_interface_lowpan_init(mac_api_t *api, char *interface_name_ptr)
|
||||
{
|
||||
|
@ -964,6 +986,22 @@ int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cer
|
|||
#endif
|
||||
}
|
||||
|
||||
int8_t arm_network_trusted_certificates_remove(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t arm_network_own_certificate_add(const arm_certificate_entry_s *cert)
|
||||
{
|
||||
(void) cert;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern int8_t arm_network_own_certificates_remove(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t arm_network_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
|
||||
{
|
||||
#ifdef HAVE_WS
|
||||
|
@ -1481,3 +1519,34 @@ int arm_nwk_sleepy_device_parent_buffer_size_set(int8_t interface_id, uint16_t b
|
|||
return -1;
|
||||
}
|
||||
|
||||
int8_t arm_nwk_set_cca_threshold(int8_t interface_id, uint8_t cca_threshold)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !cur->mac_api || (cca_threshold > 100)) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macCCAThreshold;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &cca_threshold;
|
||||
set_req.value_size = sizeof(cca_threshold);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !cur->mac_api || (tx_power > 100)) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macTXPower;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &tx_power;
|
||||
set_req.value_size = sizeof(tx_power);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ SRCS += \
|
|||
source/6LoWPAN/Thread/thread_router_bootstrap.c \
|
||||
source/6LoWPAN/Thread/thread_discovery.c \
|
||||
source/6LoWPAN/Thread/thread_commissioning_if.c \
|
||||
source/6LoWPAN/Thread/thread_bbr_commercial.c \
|
||||
source/6LoWPAN/Thread/thread_net_config_api.c \
|
||||
source/6LoWPAN/Thread/thread_network_data_lib.c \
|
||||
source/6LoWPAN/Thread/thread_network_data_storage.c \
|
||||
|
@ -187,8 +188,10 @@ SRCS += \
|
|||
source/6LoWPAN/Thread/thread_mdns.c \
|
||||
source/6LoWPAN/Thread/thread_beacon.c \
|
||||
source/6LoWPAN/Thread/thread_mle_message_handler.c \
|
||||
source/6LoWPAN/Thread/thread_lowpower_api.c \
|
||||
source/6LoWPAN/Thread/thread_lowpower_private_api.c \
|
||||
source/6LoWPAN/Thread/thread_nvm_store.c \
|
||||
source/6LoWPAN/Thread/thread_ccm.c \
|
||||
source/DHCPv6_Server/DHCPv6_Server_service.c \
|
||||
source/DHCPv6_client/dhcpv6_client_service.c \
|
||||
source/libDHCPv6/dhcp_service_api.c \
|
||||
|
|
Loading…
Reference in New Issue