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: 4a19dc4784d05a49981a8dce27bed6771e65feb5
pull/11335/head
Jarkko Paso 2019-08-26 15:10:36 +03:00
parent c51a57a033
commit b7910939da
79 changed files with 5505 additions and 653 deletions

View File

@ -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 */
};

View File

@ -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 */

View File

@ -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
}

View File

@ -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;

View File

@ -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.

View File

@ -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. */

View File

@ -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.

View File

@ -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.
*

View File

@ -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_ */

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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 */

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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) {

View File

@ -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];

View File

@ -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_ */

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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);

View File

@ -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.
*

View File

@ -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"

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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_ */

View File

@ -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;

View File

@ -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"

View File

@ -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 *)&timestamp);
@ -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

View File

@ -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_ */

View File

@ -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);

View File

@ -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)

View File

@ -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.

View File

@ -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) {

View File

@ -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 = &eth_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(&ethernet_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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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) {

View File

@ -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 */

View File

@ -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;

View File

@ -83,7 +83,8 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, struct protocol_interfac
void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair);
bool rpl_instance_local_repair(const rpl_instance_t *instance);
uint16_t rpl_instance_current_rank(const rpl_instance_t *instance);
bool rpl_instance_address_is_parent(rpl_instance_t *instance, const uint8_t *ipv6_addr, bool 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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -17,5 +17,6 @@
/* Thread feature is active with minimal functionality */
#define HAVE_THREAD
#define HAVE_THREAD_V2
#define HAVE_MPL

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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 \