Merge commit '7e1fb3c8420b4d7e43c740c3e779751c9eedb4fb'

* commit '7e1fb3c8420b4d7e43c740c3e779751c9eedb4fb':
  Squashed 'features/nanostack/sal-stack-nanostack/' changes from 82bbdcc..4a188ea
pull/7737/head
Deepak Venugopal 2018-08-08 16:51:52 +03:00
commit edfeecdab8
171 changed files with 8434 additions and 4883 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,6 +18,7 @@
#define CCMLIB_H_
#include "ns_types.h"
#include "platform/arm_hal_aes.h"
/**
*
@ -25,11 +26,11 @@
* \brief CCM Library API.
*
* \section ccm-api CCM Library API:
* - ccm_sec_init(), A function to init CCM library.
* - ccm_sec_init(), A function to init CCM context.
* - ccm_process_run(), A function to run configured CCM process.
*
* \section ccm-instruction CCM process sequence:
* 1. Init CCM library by, ccm key, ccm_sec_init()
* 1. Init CCM context by, ccm key, ccm_sec_init()
* - security level
* - 128-bit CCM key
* - mode: AES_CCM_ENCRYPT or AES_CCM_DECRYPT
@ -41,11 +42,6 @@
* -If 0 Process ok
* -< 0 MIC fail or parameter fail
*
* \section ccm-mutex CCM Mutex for Multi Thread System
* If you are running a multi thread system and the CCM library will be used for multiple thread, do the following:
* 1. Add compiler flag to library build process CCM_USE_MUTEX.
* 2. Define OS-specific mutex at the application.
* 3. Implement arm_ccm_mutex_lock() arm_ccm_mutex_unlock() function for using the generated and initialized mutex.
*/
#ifdef __cplusplus
extern "C" {
@ -63,15 +59,6 @@ extern "C" {
#define AES_CCM_DECRYPT 0x01 /**< Decryption mode */
/**
* \brief A function for locking CCM mutex if the OS is multi thread. If you are using single thread create an empty function.
*/
extern void arm_ccm_mutex_lock(void);
/**
* \brief A function for unlocking CCM mutex if the OS is multi thread. If you are using single thread create an empty function
*/
extern void arm_ccm_mutex_unlock(void);
/*!
* \struct ccm_globals_t
* \brief CCM global structure.
@ -83,21 +70,28 @@ typedef struct {
uint16_t data_len; /**< Length of data IN. */
const uint8_t *adata_ptr; /**< Pointer to authentication data. */
uint16_t adata_len; /**< Length of authentication data. */
unsigned ccm_encode_mode:1; /**< Encryption modeAES_CCM_ENCRYPT or AES_CCM_DECRYPT. */
unsigned ccm_sec_level:3; /**< Encryption operation security level 0-7. */
unsigned ccm_l_param:4; /**< Can be 2 or 3. 2 when NONCE length is 13 and 3 when 12*/
uint8_t mic_len; /**< ccm_sec_init() sets here the length of MIC. */
uint8_t *mic; /**< Encrypt process writes MIC. Decrypt reads it and compares it with the MIC obtained from data. */
const uint8_t *key_ptr; /**< Encyption key pointer to 128-bit key. */
arm_aes_context_t *aes_context; /**< Allocated AES context. */
} ccm_globals_t;
/**
* \brief A function to initialize the CCM library.
* \brief A function to initialize the CCM context.
* \param ccm_context pointer to initialized XXM context
* \param sec_level Used CCM security level (0-7).
* \param ccm_key Pointer to 128-key.
* \param mode AES_CCM_ENCRYPT or AES_CCM_DECRYPT.
* \param ccm_l Can be 2 or 3. 2 when NONCE length is 13 and 3 when 12. (NONCE length = (15-ccm_l))
*
* \return Pointer to Global CCM parameter buffer.
* \return 0 When parameter fails or CCM is busy.
* \return true when AES context allocation is OK and given parameters.
* \return false CCM parameters or AES context allocation fail.
*/
extern ccm_globals_t *ccm_sec_init(uint8_t sec_level, const uint8_t *ccm_key, uint8_t mode, uint8_t ccm_l);
extern bool ccm_sec_init(ccm_globals_t *ccm_context, uint8_t sec_level, const uint8_t *ccm_key, uint8_t mode, uint8_t ccm_l);
/**
* \brief A function to run the configured CCM process.
@ -109,6 +103,14 @@ extern ccm_globals_t *ccm_sec_init(uint8_t sec_level, const uint8_t *ccm_key, ui
* \return -2 Null pointer given to function.
*/
extern int8_t ccm_process_run(ccm_globals_t *ccm_params);
/**
* \brief A function to free aes context. Call only if ccm_process_run() is not called
* \param ccm_params CCM parameters
*
*/
extern void ccm_free(ccm_globals_t *ccm_params);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -74,17 +74,16 @@ typedef bool fhss_use_broadcast_queue(const fhss_api_t *api, bool is_broadcast_a
* @param is_broadcast_addr Destination address type of packet (true if broadcast address).
* @param destination_address Destination MAC address.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @param synch_info Pointer to where FHSS synchronization info is written (if synch frame).
* @param frame_length MSDU length of the frame.
* @param phy_header_length PHY header length.
* @param phy_tail_length PHY tail length.
* @param tx_time TX time.
* @return 0 Success.
* @return -1 Transmission of the packet is currently not allowed, try again.
* @return -2 Invalid api.
* @return -3 Broadcast packet on Unicast channel (not allowed), push packet back to queue.
* @return -4 Synchronization info missing.
*/
typedef int fhss_tx_handle(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length);
typedef int fhss_tx_handle(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length, uint32_t tx_time);
/**
* @brief Check TX permission.
@ -152,6 +151,17 @@ typedef uint32_t fhss_read_timestamp(const fhss_api_t *api);
*/
typedef uint16_t fhss_get_retry_period(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu);
/**
* @brief Write synchronization info to given pointer.
* @param api FHSS instance.
* @param ptr Pointer to data. Start of written data for Synch frame. Start of IE header for Data frame.
* @param length Length of IE header. Ignored when Synch frame.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @param tx_time TX time must be referenced to the first symbol following the SFD of the transmitted frame.
* @return -1 on fail, write length otherwise.
*/
typedef int16_t fhss_write_synch_info(const fhss_api_t *api, uint8_t *ptr, uint8_t length, int frame_type, uint32_t tx_time);
/**
* @brief Initialize MAC functions.
* @param api FHSS instance.
@ -177,6 +187,7 @@ struct fhss_api {
fhss_synch_state_set *synch_state_set; /**< Change synchronization state. */
fhss_read_timestamp *read_timestamp; /**< Read timestamp. */
fhss_get_retry_period *get_retry_period; /**< Get retransmission period. */
fhss_write_synch_info *write_synch_info; /**< Write synchronization info to TX frame*/
fhss_init_callbacks *init_callbacks; /**< Initialize MAC functions. */
};
@ -256,6 +267,18 @@ typedef int mac_broadcast_notify(const fhss_api_t *fhss_api, uint32_t broadcast_
*/
typedef int mac_read_coordinator_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address);
/**
* @brief Read synchronization info for a specific peer.
* @param fhss_api FHSS instance.
* @param info_ptr Pointer to info data.
* @param mac_address MAC address pointer.
* @param info_type Type of the read info (UTT-IE, BT-IE, US-IE, BS-IE).
* @param rx_timestamp Time of reception of the element.
* @return >=0 Length of the info.
* @return -1 Fail.
*/
typedef int mac_read_synch_info(const fhss_api_t *fhss_api, uint8_t *info_ptr, uint8_t *mac_address, int info_type, uint32_t rx_timestamp);
/**
* \brief Struct fhss_callback defines functions that software MAC needs to implement.
* Function pointers are passed to FHSS using fhss_init_callbacks function.
@ -270,6 +293,7 @@ struct fhss_callback {
mac_tx_poll *tx_poll; /**< Poll TX queue. */
mac_broadcast_notify *broadcast_notify; /**< Broadcast channel notification from FHSS. */
mac_read_coordinator_mac_address *read_coord_mac_address; /**< Read coordinator MAC address. */
mac_read_synch_info *read_synch_info; /**< Read information element for a specific MAC address. */
};
#ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,6 +28,23 @@
extern "C" {
#endif
#include "fhss_ws_extension.h"
/**
* @brief WS channel functions.
*/
typedef enum
{
/** Fixed channel. */
WS_FIXED_CHANNEL,
/** TR51 channel function. */
WS_TR51CF,
/** Direct Hash channel function. */
WS_DH1CF,
/** Vendor Defined channel function. */
WS_VENDOR_DEF_CF
} fhss_ws_channel_functions;
/**
* \brief Struct fhss_tuning_parameter defines FHSS tuning parameters.
* All delays are given in microseconds.
@ -63,20 +80,59 @@ typedef struct fhss_configuration
} fhss_configuration_t;
/**
* @brief Get channel using vendor defined channel function.
* @param api FHSS instance.
* @param slot Slot number in channel schedule.
* @param eui64 EUI-64 address of node for which the (unicast) schedule is calculated. NULL for broadcast schedule.
* @param bsi Broadcast schedule identifier used in (broadcast) schedule calculation.
* @param number_of_channels Number of channels in schedule.
* @return Channel.
*/
typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uint8_t eui64[8], uint16_t bsi, uint16_t number_of_channels);
/**
* \brief Struct fhss_ws_configuration defines configuration of WS FHSS.
*/
typedef struct fhss_ws_configuration
{
/** WS channel function. */
fhss_ws_channel_functions ws_channel_function;
/** Broadcast schedule identifier. */
uint16_t bsi;
/** Unicast dwell interval. Range: 15-250 milliseconds. */
uint8_t fhss_uc_dwell_interval;
/** Broadcast interval. Duration between broadcast dwell intervals. Range: 0-16777216 milliseconds. */
uint32_t fhss_broadcast_interval;
/** Broadcast dwell interval. Range: 15-250 milliseconds. */
uint8_t fhss_bc_dwell_interval;
/** Channel mask. */
uint32_t channel_mask[8];
/** Vendor defined channel function. */
fhss_vendor_defined_cf *vendor_defined_cf;
} fhss_ws_configuration_t;
/**
* \brief Struct fhss_timer defines interface between FHSS and FHSS platform timer.
* Application must implement FHSS timer driver which is then used by FHSS with this interface.
*/
typedef struct fhss_timer
{
/** Start timeout (1us) */
/** Start timeout (1us). Timer must support multiple simultaneous timeouts */
int (*fhss_timer_start)(uint32_t, void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t), const fhss_api_t *fhss_api);
/** Stop timeout */
int (*fhss_timer_stop)(const fhss_api_t *fhss_api);
int (*fhss_timer_stop)(void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t), const fhss_api_t *fhss_api);
/** Get remaining time of started timeout*/
uint32_t (*fhss_get_remaining_slots)(const fhss_api_t *fhss_api);
uint32_t (*fhss_get_remaining_slots)(void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t), const fhss_api_t *fhss_api);
/** Get timestamp since initialization of driver. Overflow of 32-bit counter is allowed (1us) */
uint32_t (*fhss_get_timestamp)(const fhss_api_t *fhss_api);

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file fhss_ws_extension.h
* \brief
*/
#ifndef FHSS_WS_EXT_H
#define FHSS_WS_EXT_H
#include "ns_types.h"
#include "fhss_api.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief unicast_timing_info Unicast timing/hopping schedule information structure.
*/
typedef struct unicast_timing_info {
unsigned unicast_channel_function:3; /**< Unicast schedule channel function */
uint8_t unicast_dwell_interval; /**< Unicast dwell interval */
uint16_t unicast_number_of_channels; /**< Unicast number of channels */
uint_fast24_t ufsi; /**< Unicast fractional sequence interval */
uint32_t utt_rx_timestamp; /**< UTT-IE reception timestamp */
} unicast_timing_info_t;
/**
* @brief broadcast_timing_info Broadcast timing/hopping schedule information structure.
*/
typedef struct broadcast_timing_info {
unsigned broadcast_channel_function:3; /**< Broadcast schedule channel function */
uint8_t broadcast_dwell_interval; /**< Broadcast dwell interval */
uint16_t broadcast_slot; /**< Broadcast slot number */
uint16_t broadcast_schedule_id; /**< Broadcast schedule identifier */
uint_fast24_t broadcast_interval_offset; /**< Broadcast interval offset */
uint32_t broadcast_interval; /**< Broadcast interval */
uint32_t bt_rx_timestamp; /**< BT-IE reception timestamp */
} broadcast_timing_info_t;
/**
* @brief fhss_ws_neighbor_timing_info Neighbor timing/hopping schedule information structure.
*/
typedef struct fhss_ws_neighbor_timing_info {
uint8_t clock_drift; /**< Neighbor clock drift */
uint8_t timing_accuracy; /**< Neighbor timing accuracy */
unicast_timing_info_t uc_timing_info; /**< Neighbor unicast timing info */
broadcast_timing_info_t bc_timing_info; /**< Neighbor broadcast timing info */
uint32_t *excluded_channels; /**< Neighbor excluded channels (bit mask) */
} fhss_ws_neighbor_timing_info_t;
/**
* @brief Get neighbor timing/hopping schedule.
* @param api FHSS instance.
* @param eui64 EUI-64 address of node for which the info is requested.
* @return Neighbor timing/hopping schedule.
*/
typedef fhss_ws_neighbor_timing_info_t *fhss_get_neighbor_info(const fhss_api_t *api, uint8_t eui64[8]);
/**
* @brief Set parent which broadcast channels must be listened by FHSS.
* @param fhss_api FHSS instance.
* @param eui64 EUI-64 address of parent.
* @param bc_timing_info Pointer to parent broadcast timing/hopping schedule info.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info);
/**
* @brief Remove parent which was set by ns_fhss_ws_set_parent function.
* @param fhss_api FHSS instance.
* @param eui64 EUI-64 address of parent.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_ws_remove_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8]);
/**
* @brief Set neighbor timing/hopping schedule request function.
* @param fhss_api FHSS instance.
* @param get_neighbor_info Neighbor info function pointer.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_set_neighbor_info_fp(const fhss_api_t *fhss_api, fhss_get_neighbor_info *get_neighbor_info);
/**
* @brief Set node hop count. Hop count is used to specify TX/RX slot. When hop count is set to 0xFF, TX/RX slots are ignored.
* @param fhss_api FHSS instance.
* @param hop_count Hop count to be set.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_ws_set_hop_count(const fhss_api_t *fhss_api, const uint8_t hop_count);
#ifdef __cplusplus
}
#endif
#endif // FHSS_WS_EXT_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -32,6 +32,8 @@
extern "C" {
#endif
struct channel_list_s;
typedef struct mac_api_s mac_api_t;
/**
@ -120,6 +122,17 @@ typedef void mlme_request(const mac_api_t* api, mlme_primitive id, const void *d
*/
typedef void mcps_data_request(const mac_api_t* api, const mcps_data_req_t *data);
/**
* @brief mcps_request MCPS_DATA with IE extions request call
* @param api API to handle the request
* @param data MCPS-DATA.request specific values
* @param ie_ext Information element list to MCPS-DATA.request
* @param asynch_channel_list Optional channel list to asynch data request. Give NULL when normal data request.
*
* Asynch data request is mac standard extension. asynch_channel_list include channel mask which channel message is requested to send.
*/
typedef void mcps_data_request_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const struct channel_list_s *asynch_channel_list);
/**
* @brief mcps_purge_request MCPS_PURGE request call
* @param api API to handle the request
@ -136,6 +149,14 @@ typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data);
*/
typedef void mcps_data_confirm(const mac_api_t* api, const mcps_data_conf_t *data);
/**
* @brief mcps_data_confirm_ext MCPS-DATA confirm with Enhanced ACK payload is called as a response to MCPS-DATA request
* @param api The API which handled the response
* @param data MCPS-DATA.confirm specific values
* @param conf_data Possible Confirmation Data
*/
typedef void mcps_data_confirm_ext(const mac_api_t* api, const mcps_data_conf_t *data, const mcps_data_conf_payload_t *conf_data);
/**
* @brief mcps_data_indication MCPS-DATA indication is called when MAC layer has received data
* @param api The API which handled the response
@ -143,6 +164,24 @@ typedef void mcps_data_confirm(const mac_api_t* api, const mcps_data_conf_t *dat
*/
typedef void mcps_data_indication(const mac_api_t* api, const mcps_data_ind_t *data);
/**
* @brief mcps_data_indication MCPS-DATA indication is called when MAC layer has received data
* @param api The API which handled the response
* @param data MCPS-DATA.indication specific values
* @param ie_ext Information element list
*/
typedef void mcps_data_indication_ext(const mac_api_t* api, const mcps_data_ind_t *data, const mcps_data_ie_list_t *ie_ext);
/**
* @brief mcps_ack_data_req_ext Callback for request IE elements and payload to enhanced ACK
* @param api The API which handled the response
* @param data Pointer where MAC user set Payload and IE element pointers and length
* @param rssi Signal strength for received packet
* @param lqi Link quality to neighbor
*/
typedef void mcps_ack_data_req_ext(const mac_api_t* api, mcps_ack_data_payload_t *data, int8_t rssi, uint8_t lqi);
/**
* @brief mcps_purge_confirm MCPS-PURGE confirm is called as a response to MCPS-PURGE request
* @param api The API which handled the request
@ -201,6 +240,19 @@ typedef int8_t mac_api_initialize(mac_api_t *api, mcps_data_confirm *data_conf_c
mcps_data_indication *data_ind_cb, mcps_purge_confirm *purge_conf_cb, mlme_confirm *mlme_conf_cb,
mlme_indication *mlme_ind_cb, int8_t parent_id);
/**
* @brief mac_api_enable_mcps_ext Initialises MAC 2015 extension for MCPS layer into use, callbacks must be non-NULL.
* @param api mac_api_t pointer, which is created by application.
* @param data_ind_cb Upper layer function to handle MCPS indications
* @param data_cnf_cb Upper layer function to handle MCPS confirmation
* @param ack_data_req_cb Upper layer function for set Enhanced ACK payload
* @return -1 if error, -2 if OOM, 0 otherwise
*/
typedef int8_t mac_api_enable_mcps_ext(mac_api_t *api,
mcps_data_indication_ext *data_ind_cb,
mcps_data_confirm_ext *data_cnf_cb,
mcps_ack_data_req_ext *ack_data_req_cb);
/**
* \brief Struct mac_api_s defines functions for two-way communications between external MAC and Upper layer.
* Application creates mac_api_t object by calling external MAC's creator function.
@ -209,14 +261,19 @@ typedef int8_t mac_api_initialize(mac_api_t *api, mcps_data_confirm *data_conf_c
*/
struct mac_api_s {
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
mac_api_enable_mcps_ext *mac_mcps_extension_enable; /**< MAC MCPS IE extension enable function, optional feature */
//External MAC callbacks
mlme_request *mlme_req; /**< MAC MLME request function to use */
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
mcps_data_request_ext *mcps_data_req_ext; /**< MAC MCPS data request with Information element extension function to use */
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
//Upper layer callbacksMLME_ASSOCIATE
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
mcps_data_confirm_ext *data_conf_ext_cb; /**< MAC MCPS data confirm with payload callback function */
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
mcps_data_indication_ext *data_ind_ext_cb; /**< MAC MCPS data indication with IE extension's callback function */
mcps_ack_data_req_ext *enhanced_ack_data_req_cb; /**< Enhanced ACK IE element and payload request from MAC user */
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
mlme_indication *mlme_ind_cb; /**< MAC MLME indication callback function */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,6 +30,7 @@
#define MAC_FRAME_VERSION_2003 0 /**< FCF - IEEE 802.15.4-2003 compatible */
#define MAC_FRAME_VERSION_2006 1 /**< FCF - IEEE 802.15.4-2006 (big payload or new security) */
#define MAC_FRAME_VERSION_2015 2 /**< FCF - IEEE 802.15.4-2015 (IE element support) */
//See IEEE standard 802.15.4-2006 (table 96) for more details about identifiers
#define MAC_KEY_ID_MODE_IMPLICIT 0 /**< Key identifier mode implicit */
@ -66,4 +67,36 @@ typedef struct mlme_security_s {
uint8_t Keysource[8]; /**< Key source */
} mlme_security_t;
#define MAC_HEADER_VENDOR_SPESIFIC_IE_ID 0x00 /**< Vendor specific Header IE element */
#define MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID 0x2a /**< External organisation defined Header IE element */
#define MAC_HEADER_TERMINATION1_IE_ID 0x7e /**< Header IE element termination when Payload element is following Header IE */
#define MAC_HEADER_TERMINATION2_IE_ID 0x7f /**< Header IE element termination when no Payload element is following Header IE but normal payload is */
/**
* @brief struct mac_header_IE_t Mac Header information element structure for parsing or write operation
* This structure encapsulates security related variables,
*/
typedef struct mac_header_IE_s {
uint8_t *content_ptr; /**< Content data */
unsigned length:7; /**< Element length 0- 127 */
uint8_t id; /**< Element ID */
} mac_header_IE_t;
#define MAC_PAYLOAD_IE_ESDU_GROUP_ID 0x00 /**< Encapsulated Service Data Unit (ESDU) Payload IE element's */
#define MAC_PAYLOAD_MLME_IE_GROUP_ID 0x01 /**< MLME nested Payload IE element's */
#define MAC_PAYLOAD_VENDOR_IE_GROUP_ID 0x02 /**< Vendor specific nested Payload IE element's */
#define MAC_PAYLOAD_MPX_IE_GROUP_ID 0x03 /**< MPX Payload IE element, IEEE 802.15.9 defined */
#define MAC_PAYLOAD_TERMINATION_IE_GROUP_ID 0x0f /**< Payload IE element terminator. Mandatory when normal payload is coming after IE element part */
/**
* @brief struct mac_header_IE_t Mac Payload information element structure for parsing or write operation
* This structure encapsulates security related variables,
*/
typedef struct mac_payload_IE_s {
uint8_t *content_ptr; /**< Content data */
unsigned length:11; /**< Element length 0- 2047 */
unsigned id:4; /**< Group ID */
} mac_payload_IE_t;
#endif /* MAC_COMMON_DEFINES_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -25,6 +25,7 @@
#include <inttypes.h>
#include "mac_common_defines.h"
/**
* @brief struct mcps_data_req_t Data request structure
*
@ -41,6 +42,8 @@ typedef struct mcps_data_req_s {
bool TxAckReq: 1; /**< Specifies whether ACK is needed or not */
bool InDirectTx:1; /**< Specifies whether indirect or direct transmission is used */
bool PendingBit: 1; /**< Specifies whether more fragments are to be sent or not */
bool SeqNumSuppressed:1; /**< True suppress sequence number from frame. This will be only checked when 2015 extension is enabled */
bool PanIdSuppressed:1; /**< True suppress PAN-id is done when possible from frame. This will be only checked when 2015 extension is enabled */
mlme_security_t Key; /**< Security key */
} mcps_data_req_t;
@ -58,6 +61,21 @@ typedef struct mcps_data_conf_s {
uint8_t tx_retries; /**< Number of retries done during sending, 0 means no retries */
} mcps_data_conf_t;
/**
* @brief struct mcps_data_conf_payload_t Data confirmatio IE extension list and payload from enhanced ACK
*
*/
typedef struct mcps_data_conf_payload_s {
uint8_t *headerIeList; /**< Header information IE's list without terminator*/
uint8_t *payloadIeList; /**< Payload information IE's list without terminator*/
uint8_t *payloadPtr; /**< Ack payload pointer */
uint16_t headerIeListLength; /**< Header information IE's list length in bytes */
uint16_t payloadIeListLength; /**< Payload information IE's list length in bytes */
uint16_t payloadLength; /**< Payload length in bytes */
} mcps_data_conf_payload_t;
/**
* @brief struct mcps_data_ind_t Data indication structure
*
@ -79,6 +97,54 @@ typedef struct mcps_data_ind_s {
uint8_t *msdu_ptr; /**< Data unit */
} mcps_data_ind_t;
/**
* @brief struct mcps_data_ie_list_t MCPS data Information element list stucture
*
* Structure for IEEE 802.15.4-2015 MCPS data extension to Indication
*/
typedef struct mcps_data_ie_list {
uint8_t *headerIeList; /**< Header information IE's list without terminator*/
uint8_t *payloadIeList; /**< Payload information IE's list without terminator*/
uint16_t headerIeListLength; /**< Header information IE's list length in bytes */
uint16_t payloadIeListLength; /**< Payload information IE's list length in bytes */
} mcps_data_ie_list_t;
/** \brief Scatter-gather descriptor for MCPS request IE Element list
*
* Slightly optimised for small platforms - we assume we won't need any
* element bigger than 64K.
*/
typedef struct ns_ie_iovec {
void *ieBase; /**< IE element pointer */
uint_fast16_t iovLen; /**< IE element length */
} ns_ie_iovec_t;
/**
* @brief struct mcps_data_req_ie_list MCPS data Information element list stuctrure
*
* Structure for IEEE 802.15.4-2015 MCPS data extension to Request
*
* IE element could be divided to multiple vector which MAC just write to message direct.
*/
typedef struct mcps_data_req_ie_list {
ns_ie_iovec_t *headerIeVectorList; /**< Header IE element list */
ns_ie_iovec_t *payloadIeVectorList; /**< Payload IE element list */
uint16_t headerIovLength; /**< Header IE element list size, set 0 when no elements */
uint16_t payloadIovLength; /**< Payload IE element list size, set 0 when no elements */
} mcps_data_req_ie_list_t;
/**
* @brief struct mcps_ack_data_payload_t IE extension list and payload for enhanced ACK
*
*/
typedef struct mcps_ack_data_payload {
struct mcps_data_req_ie_list ie_elements; /**< IE hader and payload's elements */
uint8_t *payloadPtr; /**< Ack payload pointer */
uint16_t payloadLength; /**< Payload length in bytes */
} mcps_ack_data_payload_t;
/**
* @brief struct mcps_purge_t Purge request structure
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -264,6 +264,7 @@ typedef enum {
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
macDefaultKeySource = 0x7c, /*<Default key source*/
//NON standard extension
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 */
macLoadBalancingBeaconTx = 0xfd, /*< Trig Beacon from load balance module periodic */
macLoadBalancingAcceptAnyBeacon = 0xfe, /*<Beacon accept state control from other network. Value size bool, data true=Enable, false=disable .*/
macThreadForceLongAddressForBeacon = 0xff /*<Thread standard force beacon source address for extended 64-bit*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,6 +38,15 @@ extern "C" {
*/
extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics);
/**
* @brief TODO: description.
* @param fhss_configuration Basic FHSS configuration.
* @param fhss_timer FHSS platform timer interface and configuration.
* @param fhss_statistics FHSS statistics storage.
* @return New FHSS instance if successful, NULL otherwise.
*/
extern fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer);
/**
* @brief Set synchronization time configuration for FHSS network. Should be only called from Border router.
* @param fhss_api FHSS instance.
@ -46,6 +55,21 @@ extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration
*/
extern int ns_fhss_configuration_set(fhss_api_t *fhss_api, const fhss_synch_configuration_t *fhss_synch_configuration);
/**
* @brief Get WS configuration.
* @param fhss_api FHSS instance.
* @return WS configuration.
*/
extern const fhss_ws_configuration_t *ns_fhss_ws_configuration_get(const fhss_api_t *fhss_api);
/**
* @brief Set WS configuration.
* @param fhss_api FHSS instance.
* @param fhss_configuration Basic FHSS configuration.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_ws_configuration_set(const fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration);
/**
* @brief Deletes a FHSS API instance and removes it from software MAC.
* @param fhss_api FHSS instance.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -166,6 +166,7 @@ typedef enum {
NET_6LOWPAN_ND_WITHOUT_MLE, /**< **UNSUPPORTED** */
NET_6LOWPAN_ND_WITH_MLE, /**< 6LoWPAN ND with MLE. */
NET_6LOWPAN_THREAD, /**< 6LoWPAN Thread with MLE attached. */
NET_6LOWPAN_WS , /**< WS. */
NET_6LOWPAN_ZIGBEE_IP /**< **UNSUPPORTED** */
} net_6lowpan_mode_extension_e;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -36,19 +36,33 @@
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* This API must be able to provide this many simultaneous contexts */
#if 1 /* config option for 802.15.4-2015? */
#define ARM_AES_MBEDTLS_CONTEXT_MIN 2 /**</ event loop and driver rx callback context */
#else
#define ARM_AES_MBEDTLS_CONTEXT_MIN 1 /**</ event loop use only */
#endif
typedef struct arm_aes_context arm_aes_context_t;
/**
* \brief Set the AES key
*
* This function sets the 128-bit AES key that will be used for future
* calls to arm_aes_encrypt(). The key must be copied by the function.
* Function must return unique pointer for every started AES context.
*
* \param key pointer to 128-bit AES key
*
* \return Pointer to aes context
* \return NULL if aes context allocation fail
*/
void arm_aes_start(const uint8_t key[__static 16]);
arm_aes_context_t *arm_aes_start(const uint8_t key[__static 16]);
/**
* \brief This function performs dst=E[preset key,src] (Simple ECB block).
@ -57,10 +71,12 @@ void arm_aes_start(const uint8_t key[__static 16]);
* It is called between arm_aes_start() and arm_aes_finish().
* Note that src and dst pointers may be equal.
*
* \param aes_context Pointer for allocated
* \param src pointer to 128-bit plaintext in
* \param dst pointer for 128-bit ciphertext out
*/
extern void arm_aes_encrypt(
arm_aes_context_t *aes_context,
const uint8_t src[__static 16],
uint8_t dst[__static 16]);
@ -69,9 +85,9 @@ extern void arm_aes_encrypt(
*
* This function is called to terminate a series of AES operations.
* It may be a no-op, or it may disable AES hardware. Use of the preset key is
* no longer valid after this call.
* no longer valid after this call and aes context will be freed.
*/
void arm_aes_finish(void);
void arm_aes_finish(arm_aes_context_t *aes_context);
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -45,6 +45,7 @@ typedef enum {
PHY_LINK_TX_SUCCESS, /**< MAC TX complete. MAC will a make decision to enter wait ACK or TX done state. */
PHY_LINK_TX_FAIL, /**< Link TX process fail. */
PHY_LINK_CCA_FAIL, /**< RF link CCA process fail. */
PHY_LINK_CCA_PREPARE, /**< RX Tx timeout prepare operation like channel switch to Tx channel from Receive one If operation fail must return not zero*/
} phy_link_tx_status_e;
/** Extension types */
@ -56,6 +57,13 @@ typedef enum {
PHY_EXTENSION_READ_LINK_STATUS, /**< Net library could read link status. */
PHY_EXTENSION_CONVERT_SIGNAL_INFO, /**< Convert signal info. */
PHY_EXTENSION_ACCEPT_ANY_BEACON, /**< Set boolean true or false for accept beacon from other Pan-ID than configured. Default value should be false */
PHY_EXTENSION_SET_TX_TIME, /**< Net library sets transmission time based on global time stamp. Max. 65ms from setting to TX. If TX time is set to zero, it should be ignored.*/
PHY_EXTENSION_READ_RX_TIME, /**< Read the time of last reception based on global micro seconds time stamp. */
PHY_EXTENSION_READ_TX_FINNISH_TIME, /**< Read the time of last finished TX micro seconds based on global time stamp. */
PHY_EXTENSION_DYNAMIC_RF_SUPPORTED, /**< Read status for support Radio driver support for set TX time, CCA and Timestamp read. Also PHY_LINK_CCA_PREPARE tx status must be supported also*/
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_type_e;
/** Address types */
@ -110,6 +118,12 @@ typedef struct phy_signal_info_s {
uint16_t result; /**< Resulting signal information. */
} phy_signal_info_s;
/** CSMA-CA parameters */
typedef struct phy_csma_params {
uint32_t backoff_time; /**< CSMA Backoff us time before start CCA & TX. 0 should disable current backoff*/
bool cca_enabled; /**< True will affect CCA check false start TX direct after backoff */
} phy_csma_params_t;
/** PHY modulation scheme */
typedef enum phy_modulation_e
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -66,6 +66,13 @@ extern int8_t ns_sw_mac_virtual_client_unregister(struct mac_api_s *api);
*/
extern int ns_sw_mac_fhss_register(struct mac_api_s *mac_api, struct fhss_api *fhss_api);
/**
* @brief Request registered FHSS API instance from software MAC instance.
* @param mac_api MAC instance.
* @return FHSS api.
*/
extern struct fhss_api *ns_sw_mac_get_fhss_api(struct mac_api_s *mac_api);
/**
* @brief Start collecting statistics from software MAC.
* @param mac_api MAC instance.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -75,6 +75,19 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
*
*/
int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
/**
* Set prefix to be used as combining multiple thread networks on backbone.
*
* update prefix value
*
* \param interface_id interface ID of the Thread network.
* \param prefix value must be buffer at the size of 8 bytes
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
/**
* Set the Thread validation interface destination address.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -54,6 +54,7 @@ typedef struct thread_border_router_info_t {
bool P_default_route: 1; /**< This device provides the default route. */
bool P_on_mesh: 1; /**< This prefix is considered to be on-mesh */
bool P_nd_dns: 1; /**< this border router is able to provide DNS information */
bool P_res1: 1; /**< First reserved bit */
bool stableData: 1; /**< This data is stable and expected to be available at least 48h. */
} thread_border_router_info_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -96,7 +96,7 @@ typedef struct link_configuration {
#define SECURITY_POLICY_EXTERNAL_COMMISSIONER_ALLOWED 0x10 /**< This indicates that external Commissioner authentication is allowed using PSKc. */
#define SECURITY_POLICY_BEACON_PAYLOAD_ENABLED 0x08 /**< Thread 1.x Beacons are enabled when this is set. */
/*
/**
* Mandatory device information
*
* This information is required if commissioning is enabled for this device.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -69,8 +69,11 @@
#endif
#include "sw_mac.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP_LOWPAN "6lo"
@ -164,7 +167,7 @@ void protocol_6lowpan_stack(buffer_t *b)
case B_TO_PHY:
b = lowpan_adaptation_data_process_tx_preprocess(cur, b);
if (lowpan_adaptation_interface_tx(cur, b) != 0) {
tr_error("Adaptaion Layer Data req fail");
tr_error("Adaptation Layer Data req fail");
}
b = NULL;
break;
@ -347,7 +350,6 @@ void protocol_6lowpan_host_init(protocol_interface_info_entry_t *cur, bool sleep
}
//Clear always INTERFACE_NWK_ROUTER_DEVICE, INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE
cur->lowpan_info &= ~(INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE);
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
mac_data_poll_init(cur);
arm_nwk_6lowpan_borderrouter_data_free(cur);
@ -358,7 +360,6 @@ void protocol_6lowpan_router_init(protocol_interface_info_entry_t *cur)
cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER;
cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
mac_data_poll_init(cur);
arm_nwk_6lowpan_borderrouter_data_free(cur);
}
@ -398,6 +399,7 @@ void protocol_6lowpan_register_handlers(protocol_interface_info_entry_t *cur)
* for routers, as RPL doesn't deal with it) */
cur->ipv6_neighbour_cache.send_addr_reg = true;
cur->ipv6_neighbour_cache.recv_na_aro = true;
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = false;
}
void protocol_6lowpan_release_short_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint16_t shortAddress)
{
@ -430,28 +432,27 @@ void protocol_6lowpan_release_long_link_address_from_neighcache(protocol_interfa
}
#ifdef HAVE_6LOWPAN_ND
static int8_t mle_set_link_priority(int8_t interface_id, const uint8_t *address, bool priority)
static int8_t mle_set_link_priority(protocol_interface_info_entry_t *cur, const uint8_t *address, bool priority)
{
uint8_t mac64[8];
mle_neigh_table_entry_t *mle_entry;
mac_neighbor_table_entry_t *entry;
if (!memcmp(address, ADDR_SHORT_ADR_SUFFIC, 6)) {
mle_entry = mle_class_get_by_link_address(interface_id, address + 6, ADDR_802_15_4_SHORT);
entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address + 6, ADDR_802_15_4_SHORT);
} else {
memcpy(mac64, address, 8);
mac64[0] ^= 2;
mle_entry = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG);
entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), mac64, ADDR_802_15_4_LONG);
}
if (!mle_entry) {
if (!entry) {
return -1;
}
if (priority) {
mle_entry->priorityFlag = 1;
entry->link_role = PRIORITY_PARENT_NEIGHBOUR;
} else {
mle_entry->priorityFlag = 0;
entry->link_role = NORMAL_NEIGHBOUR;
}
return 0;
}
@ -461,11 +462,11 @@ void protocol_6lowpan_neighbor_priority_update(protocol_interface_info_entry_t *
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
if (removed_priority) {
mle_set_link_priority(cur->id,removed_priority, false);
mle_set_link_priority(cur,removed_priority, false);
}
if (updated_priority) {
mle_set_link_priority(cur->id, updated_priority, true);
mle_set_link_priority(cur, updated_priority, true);
}
#endif
}
@ -476,30 +477,30 @@ void protocol_6lowpan_neighbor_priority_update(protocol_interface_info_entry_t *
uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
{
mle_neigh_table_entry_t *neigh_table_ptr;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!addr_ptr) {
if (!cur || !addr_ptr) {
return 0;
}
neigh_table_ptr = mle_class_get_by_link_address(interface_id, addr_ptr + PAN_ID_LEN, addr_type);
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
if (neigh_table_ptr) {
if (entry) {
etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index);
// If primary parent has changed clears priority from previous parent
if (!neigh_table_ptr->priorityFlag) {
if (entry->link_role != PRIORITY_PARENT_NEIGHBOUR) {
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST);
}
neigh_table_ptr->priorityFlag = 1;
entry->link_role = PRIORITY_PARENT_NEIGHBOUR;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur) {
uint8_t temp[2];
common_write_16_bit(neigh_table_ptr->short_adr, temp);
common_write_16_bit(entry->mac16, temp);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, temp);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG, neigh_table_ptr->mac64);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG, entry->mac64);
if (etx_entry) {
protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4);
}
protocol_stats_update(STATS_ETX_1ST_PARENT, neigh_table_ptr->etx >> 4);
return 1;
} else {
return 0;
@ -508,21 +509,26 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t
uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
{
mle_neigh_table_entry_t *neigh_table_ptr;
if (!addr_ptr) {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !addr_ptr) {
return 0;
}
neigh_table_ptr = mle_class_get_by_link_address(interface_id, addr_ptr + PAN_ID_LEN, addr_type);
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
if (neigh_table_ptr) {
if (entry) {
etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index);
// If secondary parent has changed clears priority from previous parent
if (neigh_table_ptr->second_priority_flag == 0) {
if (entry->link_role != SECONDARY_PARENT_NEIGHBOUR) {
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND);
}
neigh_table_ptr->second_priority_flag = 1;
protocol_stats_update(STATS_ETX_2ND_PARENT, neigh_table_ptr->etx >> 4);
entry->link_role = SECONDARY_PARENT_NEIGHBOUR;
if (etx_entry) {
protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
}
return 1;
} else {
return 0;
@ -531,21 +537,22 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr
void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_priority priority)
{
mle_neigh_table_list_t *mle_neigh_table;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
mle_neigh_table = mle_class_active_list_get(interface_id);
if (!mle_neigh_table) {
if (!cur) {
return;
}
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach(mle_neigh_table_entry_t, entry, mle_neigh_table) {
if (priority == PRIORITY_1ST) {
entry->priorityFlag = 0;
ns_list_foreach(mac_neighbor_table_entry_t, entry, mac_table_list) {
if (priority == PRIORITY_1ST && entry->link_role == PRIORITY_PARENT_NEIGHBOUR) {
entry->link_role = NORMAL_NEIGHBOUR;
} else {
if (entry->second_priority_flag) {
if (entry->link_role == SECONDARY_PARENT_NEIGHBOUR) {
protocol_stats_update(STATS_ETX_2ND_PARENT, 0);
entry->link_role = NORMAL_NEIGHBOUR;
}
entry->second_priority_flag = 0;
}
}
}
@ -558,43 +565,33 @@ void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_
int8_t protocol_6lowpan_neighbor_address_state_synch(protocol_interface_info_entry_t *cur, const uint8_t eui64[8], const uint8_t iid[8])
{
int8_t ret_val = -1;
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
mle_neigh_table_entry_t *mle_entry = 0;
mle_entry = mle_class_get_by_link_address(cur->id, eui64, ADDR_802_15_4_LONG);
if (mle_entry && !mle_entry->threadNeighbor) {
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), eui64, ADDR_802_15_4_LONG);
if (entry) {
if (memcmp(iid, ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
iid += 6;
//Set Short Address to MLE
mle_entry->short_adr = common_read_16_bit(iid);
entry->mac16 = common_read_16_bit(iid);
}
if ((mle_entry->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
if (mle_entry->handshakeReady) {
mle_entry_timeout_refresh(mle_entry);
if (!entry->ffd_device) {
if (entry->connected_device) {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry, entry->link_lifetime);
}
ret_val = 1;
} else {
ret_val = 0;
}
}
#endif
} else {
ret_val = 0;
}
return ret_val;
}
int8_t protocol_6lowpan_neighbor_remove(protocol_interface_info_entry_t *cur, uint8_t *address_ptr, addrtype_t type)
{
int8_t ret_val = 0;
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
mle_class_remove_neighbour(cur->id, address_ptr, type);
#endif
} else {
//REMOVE Something else
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address_ptr, type);
if (entry) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry);
}
return ret_val;
return 0;
}
void protocol_6lowpan_allocate_mac16(protocol_interface_info_entry_t *cur)
@ -739,7 +736,7 @@ uint8_t protocol_6lowpan_beacon_join_priority_tx(int8_t interface_id)
mle_6lowpan_data_t *mle_6lowpan_data = protocol_6lowpan_mle_data_get();
if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(interface_id);
uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur);
if (mle_neigh_cnt > mle_6lowpan_data->nbr_of_neigh_lower_threshold) {
uint16_t mle_neigh_limit;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -69,7 +69,9 @@
#include "mac_api.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "libNET/src/net_load_balance_internal.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "6LoWPAN/NVM/nwk_nvm.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
/* Fixed-point randomisation limits for randlib_randomise_base() - RFC 3315
@ -90,15 +92,16 @@ static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *han
#endif
static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_entry *cur_interface, uint8_t entry_count, uint8_t force_priority);
static uint8_t protocol_6lowpan_mle_order_last_entries(mle_neigh_table_list_t *mle_neigh_table, uint8_t entry_count);
static uint8_t protocol_6lowpan_mle_order_last_entries(int8_t interface_id,mac_neighbor_table_list_t *mac_neigh_table, uint8_t entry_count);
static uint8_t protocol_6lowpan_mle_data_allocate(void);
static bool mle_accept_request_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t* status);
static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mle_neigh_table_entry_t *cur);
static void protocol_6lowpan_neighbor_information_remove(int8_t interface_id, mle_neigh_table_entry_t *cur);
static int8_t protocol_6lowpan_host_challenge(int8_t interface_id, const uint8_t *mac64);
static int8_t protocol_6lowpan_router_challenge(int8_t interface_id, const uint8_t *mac64);
static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *cur);
static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
static bool lowpan_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
static bool protocol_6lowpan_router_challenge(protocol_interface_info_entry_t *cur_interface, const uint8_t *mac64);
static bool protocol_6lowpan_host_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64);
static void protocol_6lowpan_address_reg_ready(protocol_interface_info_entry_t *cur_interface);
static void coordinator_black_list(protocol_interface_info_entry_t *cur);
@ -158,9 +161,9 @@ uint8_t *mle_general_write_timeout(uint8_t *ptr, protocol_interface_info_entry_t
}
static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mle_neigh_table_entry_t *cur)
static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *cur)
{
if (!cur->priorityFlag ||
if (cur->link_role != PRIORITY_PARENT_NEIGHBOUR ||
!(cur_interface->lowpan_info & INTERFACE_NWK_ACTIVE) ||
cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
return;
@ -176,9 +179,9 @@ static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_en
}
} else {
//Call Priority parent loose
if (cur->short_adr != 0xffff) {
if (cur->mac16 != 0xffff) {
memcpy(mac64, ADDR_SHORT_ADR_SUFFIC, 6);
common_write_16_bit(cur->short_adr, &mac64[6]);
common_write_16_bit(cur->mac16, &mac64[6]);
} else {
memcpy(mac64,cur->mac64 , 8);
mac64[0] ^= 2;
@ -192,64 +195,42 @@ static void protocol_6lowpan_priority_neighbor_remove(protocol_interface_info_en
}
}
static void protocol_6lowpan_neighbor_information_remove(int8_t interface_id, mle_neigh_table_entry_t *cur)
static bool protocol_6lowpan_challenge_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
{
protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur_interface) {
return;
return false;
}
// Sleepy host
if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
mac_data_poll_protocol_poll_mode_decrement(cur_interface);
}
protocol_6lowpan_priority_neighbor_remove(cur_interface, cur);
if (cur->mode & MLE_FFD_DEV) {
protocol_6lowpan_release_short_link_address_from_neighcache(cur_interface, cur->short_adr);
protocol_6lowpan_release_long_link_address_from_neighcache(cur_interface, cur->mac64);
}
mac_helper_devicetable_remove(cur_interface->mac_api, cur->attribute_index);
}
static bool protocol_6lowpan_challenge_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
{
uint8_t mac64[8];
uint8_t *ll64_ptr = mle_service_get_msg_destination_address_pointer(msgId);
memcpy(mac64, ll64_ptr + 8, 8);
mac64[0] ^= 2;
mle_neigh_table_entry_t *neig_info = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG);
mac_neighbor_table_entry_t * neig_info = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), mac64, ADDR_802_15_4_LONG);
if (!neig_info) {
return false;//Why entry is removed before timeout??
}
if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) {
if (!neig_info->nud_active) {
return false;
}
if (usedAllRetries) {
//GET entry
mle_class_remove_entry(interface_id, neig_info);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur_interface), neig_info);
return false;
}
return true;
}
static int8_t protocol_6lowpan_host_challenge(int8_t interface_id, const uint8_t *mac64)
static bool protocol_6lowpan_host_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return false;
}
uint16_t bufId;
mle_message_timeout_params_t timeout;
uint8_t ll64[16];
@ -261,7 +242,7 @@ static int8_t protocol_6lowpan_host_challenge(int8_t interface_id, const uint8_t
tr_debug("Link REQUEST");
bufId = mle_service_msg_allocate(cur->id, 32, true,MLE_COMMAND_REQUEST);
if (bufId == 0) {
return -1;
return false;
}
uint8_t *ptr = mle_service_get_data_pointer(bufId);
@ -293,16 +274,11 @@ static int8_t protocol_6lowpan_host_challenge(int8_t interface_id, const uint8_t
mle_service_set_msg_timeout_parameters(bufId, &timeout);
mle_service_send_message(bufId);
return 0;
return true;
}
static int8_t protocol_6lowpan_router_challenge(int8_t interface_id, const uint8_t *mac64)
static bool protocol_6lowpan_router_challenge(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return false;
}
uint16_t bufId;
mle_message_timeout_params_t timeout;
@ -315,7 +291,7 @@ static int8_t protocol_6lowpan_router_challenge(int8_t interface_id, const uint8
tr_debug("Link REQUEST");
bufId = mle_service_msg_allocate(cur->id, 32, true,MLE_COMMAND_REQUEST);
if (bufId == 0) {
return -1;
return false;
}
uint8_t *ptr = mle_service_get_data_pointer(bufId);
@ -342,16 +318,16 @@ static int8_t protocol_6lowpan_router_challenge(int8_t interface_id, const uint8
mle_service_set_msg_timeout_parameters(bufId, &timeout);
mle_service_send_message(bufId);
return 0;
return true;
}
static uint8_t mle_advert_neigh_cnt(int8_t interface_id, bool short_adr) {
static uint8_t mle_advert_neigh_cnt(protocol_interface_info_entry_t *cur_interface, bool short_adr) {
uint8_t advert_neigh_cnt;
uint8_t neighb_max;
uint8_t mle_neigh_cnt = mle_class_active_neigh_counter(interface_id);
uint8_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
if (short_adr == true) {
neighb_max = 16;
@ -413,48 +389,55 @@ static uint8_t mle_link_quality_tlv_parse(uint8_t *mac64, uint16_t short_address
return 0;
}
static uint8_t *mle_table_set_neighbours(int8_t interface_id, uint8_t *ptr)
static bool neighbor_list_short_address_available(mac_neighbor_table_t *table_class)
{
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, &table_class->neighbour_list) {
if (cur_entry->connected_device && cur_entry->mac16 == 0xffff) {
return false;
}
}
return true;
}
static uint8_t *mle_table_set_neighbours(protocol_interface_info_entry_t *cur, uint8_t *ptr)
{
uint8_t *len_ptr = 0;
uint8_t short_temp[2] = {0xff,0xff};
uint8_t neigh_count = 0;
uint8_t neigh_count_max = 0;
uint8_t *link_flags_ptr;
mle_neigh_table_entry_t *first_entry_ptr = NULL;
bool loop_list = false;
mac_neighbor_table_entry_t *first_entry_ptr = NULL;
mle_neigh_table_list_t * neigh_list = mle_class_active_list_get(interface_id);
if (!neigh_list) {
return ptr;
}
mac_neighbor_table_list_t * neigh_list = &cur->mac_parameters->mac_neighbor_table->neighbour_list;
*ptr++ = MLE_TYPE_LINK_QUALITY;
len_ptr = ptr++;
*len_ptr = 1;
// defaults: complete, 2 bytes long link-layer address
link_flags_ptr = ptr++;
//*link_flags_ptr = 0x81;
bool use_short_address_compression = neighbor_list_short_address_available(mac_neighbor_info(cur));
if (use_short_address_compression) {
//complete, 2 bytes long link-layer address
*link_flags_ptr = 0x81;
if (mle_class_get_by_link_address(interface_id, short_temp,ADDR_802_15_4_SHORT)) {
*link_flags_ptr |= 0x07;
neigh_count_max = mle_advert_neigh_cnt(interface_id, false);
} else {
neigh_count_max = mle_advert_neigh_cnt(interface_id, true);
}
//complete, 8 bytes long link-layer address
*link_flags_ptr = 0x87;
do {
ns_list_foreach(mle_neigh_table_entry_t, cur, neigh_list)
}
neigh_count_max = mle_advert_neigh_cnt(cur, use_short_address_compression);
bool clean_entries = false;
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, neigh_list)
{
loop_list = false;
if ((cur->handshakeReady) && (cur->link_q_adv_sent == false)) {
if ((cur_entry->connected_device) && (cur_entry->advertisment == false)) {
// If looping list, stops adding entries when at first sent entry again
if (first_entry_ptr == cur) {
if (first_entry_ptr == cur_entry) {
break;
} else if (first_entry_ptr == NULL) {
first_entry_ptr = cur;
first_entry_ptr = cur_entry;
}
// Limits the number of entries that are sent
@ -463,38 +446,37 @@ static uint8_t *mle_table_set_neighbours(int8_t interface_id, uint8_t *ptr)
break;
}
if (cur->priorityFlag) {
if (cur_entry->link_role == PRIORITY_PARENT_NEIGHBOUR) {
*ptr++ = MLE_NEIGHBOR_PRIORITY_LINK | MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
} else {
*ptr++ = MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
}
*ptr++ = etx_local_incoming_idr_read(interface_id, cur) >> 3;
*ptr++ = etx_local_incoming_idr_read(cur->id, cur_entry->index) >> 3;
if ((*link_flags_ptr & 0x07) == 1) {
ptr = common_write_16_bit(cur->short_adr, ptr);
if (use_short_address_compression) {
ptr = common_write_16_bit(cur_entry->mac16, ptr);
*len_ptr += 4;
} else {
memcpy(ptr, cur->mac64, 8);
memcpy(ptr, cur_entry->mac64, 8);
ptr += 8;
*len_ptr += 10;
}
// If end of the neighbor list, start adding entries from start again
if (cur->link.next == 0) {
loop_list = true;
mle_neigh_table_list_t * neigh_temp = mle_class_active_list_get(interface_id);
ns_list_foreach(mle_neigh_table_entry_t, temp, neigh_temp)
{
// If end of the neighbor list, Mark a clean advertisment from the list
if (cur_entry->link.next == 0) {
clean_entries = true;
}
cur_entry->advertisment = true;
}
}
if (clean_entries) {
ns_list_foreach(mac_neighbor_table_entry_t, temp, neigh_list) {
// Marks entries not sent
temp->link_q_adv_sent = false;
}
} else {
cur->link_q_adv_sent = true;
temp->advertisment = false;
}
}
}
} while (loop_list);
return ptr;
}
@ -515,10 +497,10 @@ static int protocol_6lowpan_mle_neigh_advertise(protocol_interface_info_entry_t
return 0;
}
if (mle_class_get_by_link_address(cur->id, short_temp,ADDR_802_15_4_SHORT)) {
neig_cache_size += mle_advert_neigh_cnt(cur->id, false) * 10;
if (mac_neighbor_table_address_discover(mac_neighbor_info(cur), short_temp,ADDR_802_15_4_SHORT)) {
neig_cache_size += mle_advert_neigh_cnt(cur, false) * 10;
} else {
neig_cache_size += mle_advert_neigh_cnt(cur->id, true) << 2;
neig_cache_size += mle_advert_neigh_cnt(cur, true) << 2;
}
uint16_t bufId = mle_service_msg_allocate(cur->id, neig_cache_size, false, MLE_COMMAND_ADVERTISEMENT);
@ -539,7 +521,7 @@ static int protocol_6lowpan_mle_neigh_advertise(protocol_interface_info_entry_t
ptr = mle_service_get_data_pointer(bufId);
ptr = mle_general_write_source_address(ptr, cur);
ptr = mle_tlv_write_mode(ptr, lowpan_mode_get_by_interface_ptr(cur));
ptr = mle_table_set_neighbours(cur->id, ptr);
ptr = mle_table_set_neighbours(cur, ptr);
if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
tr_debug("Buffer overflow at message write");
@ -549,15 +531,6 @@ static int protocol_6lowpan_mle_neigh_advertise(protocol_interface_info_entry_t
}
#endif
static uint8_t compute_link_margin(int8_t rssi)
{
if (rssi < -94) {
return 0;
}
return (rssi + 94);
}
static int mle_validate_6lowpan_link_request_message(uint8_t *ptr, uint16_t data_len, mle_tlv_info_t *tlv_info)
{
/**
@ -571,8 +544,11 @@ static int mle_validate_6lowpan_link_request_message(uint8_t *ptr, uint16_t data
return 0;
}
static void mle_neigh_time_and_mode_update(mle_neigh_table_entry_t *entry_temp, uint8_t *tlv_ptr, uint16_t tlv_length)
static void mle_neigh_time_and_mode_update(mac_neighbor_table_entry_t *entry_temp, mle_message_t *mle_msg)
{
uint8_t *tlv_ptr = mle_msg->data_ptr;
uint16_t tlv_length = mle_msg->data_length;
mle_tlv_info_t mle_tlv_info;
uint32_t timeout_tlv;
@ -580,42 +556,44 @@ static void mle_neigh_time_and_mode_update(mle_neigh_table_entry_t *entry_temp,
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_MODE, &mle_tlv_info) > 0) {
uint8_t *t_ptr = mle_tlv_info.dataPtr;
entry_temp->mode = *t_ptr;
mle_mode_parse_to_mac_entry(entry_temp, *t_ptr);
}
if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_TIMEOUT, &mle_tlv_info) > 0) {
timeout_tlv = common_read_32_bit(mle_tlv_info.dataPtr);
} else {
if (entry_temp->mode & MLE_FFD_DEV) {
if (entry_temp->ffd_device) {
timeout_tlv = mle_6lowpan_data->router_lifetime;
} else {
timeout_tlv = mle_6lowpan_data->host_lifetime;
}
}
mle_entry_timeout_update(entry_temp, timeout_tlv);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout_tlv);
}
static void mle_neigh_entry_update_by_mle_tlv_list(int8_t interface_id, mle_neigh_table_entry_t *entry_temp, uint8_t *tlv_ptr, uint16_t tlv_length, uint8_t *mac64, uint16_t short_address)
static void mle_neigh_entry_update_by_mle_tlv_list(int8_t interface_id, mac_neighbor_table_entry_t *entry_temp, uint8_t *tlv_ptr, uint16_t tlv_length, uint8_t *mac64, uint16_t short_address)
{
mle_tlv_info_t mle_tlv_info;
if (tlv_length) {
if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_SRC_ADDRESS, &mle_tlv_info) > 0) {
entry_temp->short_adr = common_read_16_bit(mle_tlv_info.dataPtr);
entry_temp->mac16 = common_read_16_bit(mle_tlv_info.dataPtr);
}
if (mle_tlv_option_discover(tlv_ptr, tlv_length, MLE_TYPE_LINK_QUALITY, &mle_tlv_info) > 0) {
uint8_t link_idr;
uint8_t iop_flags;
if (mle_link_quality_tlv_parse(mac64, short_address, mle_tlv_info.dataPtr, mle_tlv_info.tlvLen, &iop_flags, &link_idr)) {
etx_remote_incoming_idr_update(interface_id, link_idr, entry_temp);
etx_remote_incoming_idr_update(interface_id, link_idr, entry_temp->index);
if ((iop_flags & MLE_NEIGHBOR_PRIORITY_LINK) == MLE_NEIGHBOR_PRIORITY_LINK) {
entry_temp->priority_child_flag = true;
} else {
entry_temp->priority_child_flag = false;
entry_temp->link_role = CHILD_NEIGHBOUR;
} else if (entry_temp->link_role == CHILD_NEIGHBOUR) {
entry_temp->link_role = NORMAL_NEIGHBOUR;
}
}
}
@ -758,10 +736,10 @@ static int mle_router_accept_request_build(protocol_interface_info_entry_t *cur,
static void protocol_6lowpan_link_reject_handler(protocol_interface_info_entry_t *cur, uint8_t *ll64)
{
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, 0, ll64, false, NULL);
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, false, NULL);
tr_debug("MLE link reject");
if (entry_temp) {
mle_class_remove_entry(cur->id, entry_temp);
if (mac_entry) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), mac_entry);
}
}
@ -984,14 +962,16 @@ int protocol_6lowpan_router_synch_to_new_router(protocol_interface_info_entry_t
}
static uint8_t mle_calculate_idr(int8_t interface_id, mle_message_t *mle_msg, mle_neigh_table_entry_t *entry_temp)
static uint8_t mle_calculate_idr(int8_t interface_id, mle_message_t *mle_msg, mac_neighbor_table_entry_t *entry_temp)
{
return etx_lqi_dbm_update(interface_id, mle_msg->lqi, mle_msg->dbm, entry_temp) >> 3;
if (!entry_temp) {
return etx_lqi_dbm_update(-2, mle_msg->lqi, mle_msg->dbm, 0) >> 3;
}
return etx_lqi_dbm_update(interface_id, mle_msg->lqi, mle_msg->dbm, entry_temp->index) >> 3;
}
static bool mle_6lowpan_neighbor_limit_check(int8_t interface_id, mle_message_t *mle_msg, uint8_t only_max_limit_chk)
static bool mle_6lowpan_neighbor_limit_check(mle_message_t *mle_msg, uint8_t only_max_limit_chk)
{
uint16_t mle_neigh_cnt;
bool link_quality = false;
@ -1000,7 +980,7 @@ static bool mle_6lowpan_neighbor_limit_check(int8_t interface_id, mle_message_t
return true;
}
mle_neigh_cnt = mle_class_active_neigh_counter(interface_id);
mle_neigh_cnt = mle_class_active_neigh_counter(mle_msg->interface_ptr);
// Neighbor max limit
if (mle_neigh_cnt >= mle_6lowpan_data->nbr_of_neigh_max) {
@ -1048,17 +1028,11 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
uint8_t mode = 0x0a;
mle_tlv_info_t mle_tlv_info;
mle_tlv_info_t mle_challenge;
mle_neigh_table_entry_t *entry_temp;
uint8_t linkMargin;
mac_neighbor_table_entry_t *entry_temp;
uint8_t incoming_idr;
uint16_t responseId, own_mac16;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
//Calculate link margin
linkMargin = compute_link_margin(mle_msg->dbm);
own_mac16 = mac_helper_mac16_address_get(cur);
@ -1081,13 +1055,13 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
mle_6lowpan_data->link_req_token_bucket--;
} else {
//Update only old information based on link request
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
mle_neigh_time_and_mode_update(entry_temp,mle_msg->data_ptr, mle_msg->data_length);
mle_neigh_time_and_mode_update(entry_temp,mle_msg);
mle_neigh_entry_update_by_mle_tlv_list(interface_id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
} else {
if (!mle_6lowpan_neighbor_limit_check(interface_id, mle_msg, false)) {
if (!mle_6lowpan_neighbor_limit_check(mle_msg, false)) {
return;
}
}
@ -1095,7 +1069,7 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
incoming_idr = mle_calculate_idr(interface_id, mle_msg, entry_temp);
if (entry_temp && entry_temp->handshakeReady) {
if (entry_temp && entry_temp->connected_device) {
response_type = MLE_COMMAND_ACCEPT;
} else {
response_type = MLE_COMMAND_ACCEPT_AND_REQUEST;
@ -1117,13 +1091,11 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
}
tr_debug("Accept & Request");
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (!entry_temp) {
// If there is space for neighbors try to allocate new entry
if (mle_6lowpan_neighbor_limit_check(interface_id, mle_msg, true)) {
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, true, NULL);
if (mle_6lowpan_neighbor_limit_check(mle_msg, true)) {
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, NULL);
}
}
@ -1137,23 +1109,22 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
//Response state set now timeout know positive state
mle_service_set_msg_response_true(responseId);
entry_temp->threadNeighbor = false;
entry_temp->handshakeReady = 1;
entry_temp->connected_device = 1;
mac_data_poll_protocol_poll_mode_decrement(cur);
//Read Source address and Challenge
mle_neigh_time_and_mode_update(entry_temp,mle_msg->data_ptr, mle_msg->data_length);
mle_neigh_time_and_mode_update(entry_temp,mle_msg);
if (mle_msg->message_type == MLE_COMMAND_ACCEPT_AND_REQUEST) {
// If no global address set priority (bootstrap ongoing)
if (!cur->global_address_available) {
entry_temp->priorityFlag = true;
entry_temp->link_role = PRIORITY_PARENT_NEIGHBOUR;
}
mle_neigh_entry_update_by_mle_tlv_list(cur->id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
incoming_idr = mle_calculate_idr(cur->id, mle_msg, entry_temp);
mle_router_accept_request_build(cur, mle_msg, mle_challenge.dataPtr, mle_challenge.tlvLen, MLE_COMMAND_ACCEPT, incoming_idr, entry_temp->priorityFlag);
uint8_t priority = (entry_temp->link_role == PRIORITY_PARENT_NEIGHBOUR);
mle_router_accept_request_build(cur, mle_msg, mle_challenge.dataPtr, mle_challenge.tlvLen, MLE_COMMAND_ACCEPT, incoming_idr, priority);
} else {
mle_neigh_entry_update_by_mle_tlv_list(cur->id, entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
incoming_idr = mle_calculate_idr(cur->id, mle_msg, entry_temp);
@ -1161,7 +1132,7 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
// If MLE frame counter was invalid update its value since three way handshake is complete
if (security_headers->invalid_frame_counter) {
entry_temp->mle_frame_counter = security_headers->frameCounter;
mle_service_frame_counter_entry_add(interface_id, entry_temp->index, security_headers->frameCounter);
}
break;
@ -1184,12 +1155,11 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
t_ptr = mle_tlv_info.dataPtr;
mode = *t_ptr;
}
entry_temp = mle_class_get_entry_by_ll64(interface_id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (!entry_temp) {
if ((mode & MLE_DEV_MASK) == MLE_FFD_DEV) {
// If there is space for neighbors synchronizes to new router
if (mle_6lowpan_neighbor_limit_check(interface_id, mle_msg, false)) {
if (mle_6lowpan_neighbor_limit_check(mle_msg, false)) {
// Checks blacklist
if (blacklist_reject(mle_msg->packet_src_address)) {
return;
@ -1220,7 +1190,7 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
//Possible remove
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
//Remove Entry
mle_class_remove_entry(cur->id, entry_temp);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
tr_error("MLE adv: Own address not found");
return;
}
@ -1232,8 +1202,8 @@ void mle_6lowpan_message_handler(int8_t interface_id, mle_message_t *mle_msg, ml
//UPDATE
mle_neigh_entry_update_by_mle_tlv_list(cur->id,entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur->mac, own_mac16);
mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
if (entry_temp->handshakeReady) {
mle_entry_timeout_refresh(entry_temp);
if (entry_temp->connected_device) {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime);
}
}
break;
@ -1250,7 +1220,7 @@ int8_t arm_6lowpan_mle_service_ready_for_security_init(protocol_interface_info_e
//validate MLE service
if (!mle_service_interface_registeration_validate(cur->id)) {
//Register
if (mle_service_interface_register(cur->id,mle_6lowpan_message_handler, cur->mac,8) != 0) {
if (mle_service_interface_register(cur->id,cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
tr_error("Mle Service init Fail");
return -1;
}
@ -1301,29 +1271,24 @@ mle_6lowpan_data_t *protocol_6lowpan_mle_data_get(void)
static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_entry *cur_interface, uint8_t entry_count, uint8_t force_priority)
{
mle_neigh_table_list_t *mle_neigh_table;
uint8_t count = 0;
uint8_t ll64[16];
if (!cur_interface) {
return;
}
mac_neighbor_table_list_t *mac_table_list = &cur_interface->mac_parameters->mac_neighbor_table->neighbour_list;
mle_neigh_table = mle_class_active_list_get(cur_interface->id);
entry_count = protocol_6lowpan_mle_order_last_entries(cur_interface->id, mac_table_list, entry_count);
if (!mle_neigh_table) {
return;
}
entry_count = protocol_6lowpan_mle_order_last_entries(mle_neigh_table, entry_count);
ns_list_foreach_reverse_safe(mle_neigh_table_entry_t, entry, mle_neigh_table) {
ns_list_foreach_reverse_safe(mac_neighbor_table_entry_t, entry, mac_table_list) {
if (++count > entry_count) {
break;
}
if (!force_priority) {
if (entry->priorityFlag || entry->priority_child_flag) {
if (entry->link_role == PRIORITY_PARENT_NEIGHBOUR || entry->link_role == CHILD_NEIGHBOUR) {
break;
}
}
@ -1336,23 +1301,23 @@ static void protocol_6lowpan_mle_purge_neighbors(struct protocol_interface_info_
// Sends REJECT
mle_service_reject_message_build(cur_interface->id, ll64, false);
mle_class_remove_entry(cur_interface->id, entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur_interface), entry);
// Adds purged neighbor to blacklist so that it is not added right away back from advertisement
blacklist_update(ll64, false);
}
}
static uint8_t protocol_6lowpan_mle_order_last_entries(mle_neigh_table_list_t *mle_neigh_table, uint8_t entry_count)
static uint8_t protocol_6lowpan_mle_order_last_entries(int8_t interface_id, mac_neighbor_table_list_t *mac_neigh_table, uint8_t entry_count)
{
mle_neigh_table_entry_t *last;
mle_neigh_table_entry_t *first_ordered = NULL;
mac_neighbor_table_entry_t *last;
mac_neighbor_table_entry_t *first_ordered = NULL;
etx_storage_t * etx_last, *etx_cur;
uint8_t count = 0;
do {
last = NULL;
ns_list_foreach(mle_neigh_table_entry_t, entry, mle_neigh_table) {
ns_list_foreach(mac_neighbor_table_entry_t, entry, mac_neigh_table) {
if (entry == first_ordered) {
break;
@ -1363,37 +1328,27 @@ static uint8_t protocol_6lowpan_mle_order_last_entries(mle_neigh_table_list_t *m
continue;
}
// Primary parent (parent selected for bootstrap or RPL primary parent)
if (entry->priorityFlag && !last->priorityFlag) {
if (entry->link_role > last->link_role) { //Bigger link role is allways better
continue;
} else if (entry->link_role == last->link_role) {
// Compare ETX when Link role is same
etx_cur = etx_storage_entry_get(interface_id, entry->index);
etx_last = etx_storage_entry_get(interface_id, last->index);
if (etx_cur && etx_last && etx_cur->etx <= etx_last->etx) {
continue;
}
// Secondary parent (RPL secondary parent)
if (entry->second_priority_flag && !last->second_priority_flag) {
continue;
}
// Uses this node as parent
if (entry->priority_child_flag && !last->priority_child_flag) {
continue;
}
// Better ETX
if (entry->etx <= last->etx) {
continue;
}
last = entry;
}
// Sets last to end of list
if (last) {
ns_list_remove(mle_neigh_table, last);
ns_list_remove(mac_neigh_table, last);
if (first_ordered) {
ns_list_add_before(mle_neigh_table, first_ordered, last);
ns_list_add_before(mac_neigh_table, first_ordered, last);
} else {
ns_list_add_to_end(mle_neigh_table, last);
ns_list_add_to_end(mac_neigh_table, last);
}
first_ordered = last;
@ -1431,10 +1386,11 @@ static int8_t arm_6lowpan_bootstrap_down(protocol_interface_info_entry_t *cur)
static void lowpan_mle_receive_security_bypass_cb(int8_t interface_id, mle_message_t *mle_msg)
{
(void) interface_id;
#ifdef PANA
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
protocol_interface_info_entry_t *interface = mle_msg->interface_ptr;
//Accept Only Link Reject
if (interface && mle_msg->message_type == MLE_COMMAND_REJECT) {
if (mle_msg->message_type == MLE_COMMAND_REJECT) {
if ((interface->lowpan_info & (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) != (INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION)) {
return;
@ -1508,7 +1464,7 @@ static int8_t arm_6lowpan_bootstrap_up(protocol_interface_info_entry_t *cur)
if (!mle_service_interface_registeration_validate(cur->id)) {
//Register
if (mle_service_interface_register(cur->id,mle_6lowpan_message_handler, cur->mac,8) != 0) {
if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
tr_error("Mle Service init Fail");
return -1;
}
@ -1594,7 +1550,6 @@ int8_t arm_network_processor_up(protocol_interface_info_entry_t *cur)
} else {
protocol_6lowpan_register_handlers(cur);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
mac_helper_default_security_level_set(cur, SEC_NONE);
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER) {
@ -1621,15 +1576,6 @@ int8_t arm_network_processor_up(protocol_interface_info_entry_t *cur)
return ret_val;
}
static bool lowpan_interface_is_active(int8_t interface_id) {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
return false;
}
return true;
}
static void arm_6lowpan_security_key_update_cb(protocol_interface_info_entry_t *cur, const mlme_security_t *security_params)
{
if (cur->mac_parameters->mac_next_key_index && (security_params->KeyIndex == cur->mac_parameters->mac_next_key_index)) {
@ -1641,6 +1587,66 @@ static void arm_6lowpan_security_key_update_cb(protocol_interface_info_entry_t *
}
}
}
static void lowpan_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
{
protocol_interface_info_entry_t *cur_interface = user_data;
lowpan_adaptation_remove_free_indirect_table(cur_interface, entry_ptr);
// Sleepy host
if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
mac_data_poll_protocol_poll_mode_decrement(cur_interface);
}
protocol_6lowpan_priority_neighbor_remove(cur_interface, entry_ptr);
if (entry_ptr->ffd_device) {
protocol_6lowpan_release_short_link_address_from_neighcache(cur_interface, entry_ptr->mac16);
protocol_6lowpan_release_long_link_address_from_neighcache(cur_interface, entry_ptr->mac64);
}
mac_helper_devicetable_remove(cur_interface->mac_api, entry_ptr->index);
//Removes ETX neighbor
etx_neighbor_remove(cur_interface->id, entry_ptr->index);
//Remove MLE frame counter info
mle_service_frame_counter_entry_delete(cur_interface->id, entry_ptr->index);
}
static bool lowpan_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
{
// Sleepy host
protocol_interface_info_entry_t *cur_interface = user_data;
if (cur_interface->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
//Trig middle way challenge if Broadcast message have been missed
if (!entry_ptr->ffd_device) {
return false; //End device must do this
}
if (entry_ptr->lifetime > (entry_ptr->link_lifetime / 2)) {
return false; //Trig only when midway is overed
}
return protocol_6lowpan_router_challenge(cur_interface, entry_ptr->mac64);
}
if (entry_ptr->link_role != PRIORITY_PARENT_NEIGHBOUR) {
return false; //Do not never challenge than priority parent
}
if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
return false; //Sleepy end device should not never challenge
}
if (entry_ptr->lifetime > MLE_TABLE_CHALLENGE_TIMER) {
return false;
}
return protocol_6lowpan_host_challenge(cur_interface, entry_ptr->mac64);
}
int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension)
{
int8_t ret_val = -1;
@ -1665,20 +1671,29 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode
cur->mac_security_key_usage_update_cb = arm_6lowpan_security_key_update_cb;
//Allocate MLE class here
//Deallocate old here
mle_class_deallocate(interface_id);
if (enable_mle_protocol) {
mac_neighbor_table_delete(mac_neighbor_info(cur));
mac_description_storage_size_t buffer;
//Read MAC device table sizes
if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
return -1;
}
if (mle_class_init(interface_id, buffer.device_decription_table_size, &protocol_6lowpan_neighbor_information_remove, &protocol_6lowpan_host_challenge, &lowpan_interface_is_active) != 0) {
mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size, lowpan_neighbor_entry_remove_notify
, lowpan_neighbor_entry_nud_notify, cur);
if (!mac_neighbor_info(cur)) {
return -1;
}
mle_class_router_challenge(interface_id, protocol_6lowpan_router_challenge);
if (enable_mle_protocol) {
if (mle_service_frame_counter_table_allocate(interface_id, buffer.device_decription_table_size)) {
return -1;
}
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
return -1;
}
lowpan_adaptation_interface_etx_update_enable(cur->id);
}
mle_service_interface_unregister(cur->id);
@ -1704,7 +1719,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode
return -2;
#else
cur->comm_status_ind_cb = lowpan_comm_status_indication_cb;
if (mle_service_interface_register(cur->id,mle_6lowpan_message_handler, cur->mac,8) != 0) {
if (mle_service_interface_register(cur->id, cur, mle_6lowpan_message_handler, cur->mac,8) != 0) {
tr_error("Mle Service init Fail");
return -1;
}
@ -1906,7 +1921,7 @@ void protocol_6lowpan_link_advertise_handle(nd_router_t *cur, protocol_interface
cur->mle_purge_timer -= 1;
} else {
if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface->id);
uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur_interface);
if (mle_neigh_cnt > (mle_6lowpan_data->nbr_of_neigh_max - MLE_NEIGHBOR_PURGE_NBR)) {
protocol_6lowpan_mle_purge_neighbors(cur_interface, MLE_NEIGHBOR_PURGE_NBR, true);
}
@ -1946,15 +1961,15 @@ static void protocol_6lowpan_nd_ready(protocol_interface_info_entry_t *cur)
if ((cur->lowpan_info & (INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE | INTERFACE_NWK_BOOTSRAP_MLE)) == INTERFACE_NWK_BOOTSRAP_MLE) {
//TRIG Only Normal Host
#ifndef NO_MLE
//GET Cordinaotor MLE Entry
//GET Cordinator MLE Entry
addrtype_t addrType;
uint8_t tempAddr[8];
addrType = mac_helper_coordinator_address_get(cur, tempAddr);
mac_neighbor_table_entry_t * neig_info = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tempAddr, addrType);
mle_neigh_table_entry_t *entry_t = mle_class_get_by_link_address(cur->id, tempAddr, addrType);
if (entry_t) {
if (entry_t->ttl > MLE_TABLE_CHALLENGE_TIMER) {
entry_t->ttl = (MLE_TABLE_CHALLENGE_TIMER + 1);
if (neig_info) {
if (neig_info->lifetime > MLE_TABLE_CHALLENGE_TIMER) {
neig_info->lifetime = (MLE_TABLE_CHALLENGE_TIMER + 1);
}
}
#endif
@ -2175,7 +2190,6 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t *
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) {
cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
tr_debug("Enable Poll state");
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
mac_data_poll_init(cur);
mac_data_poll_init_protocol_poll(cur);
@ -2753,12 +2767,13 @@ static void protocol_6lowpan_generate_link_reject(protocol_interface_info_entry_
static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t* status)
{
#ifndef NO_MLE
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(if_id);
if (!cur) {
return;
}
mac_neighbor_table_entry_t * entry_ptr;
switch (status->status) {
case MLME_UNSUPPORTED_SECURITY:
case MLME_UNAVAILABLE_KEY:
@ -2775,29 +2790,33 @@ static void lowpan_comm_status_indication_cb(int8_t if_id, const mlme_comm_statu
break;
case MLME_DATA_POLL_NOTIFICATION:
mle_refresh_entry_timeout(if_id, status->SrcAddr, (addrtype_t)status->SrcAddrMode, false);
entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), status->SrcAddr, status->SrcAddrMode);
if (entry_ptr) {
// Refresh Timeout
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_ptr, entry_ptr->link_lifetime);
}
break;
default:
break;
}
#endif
}
bool lowpan_neighbour_data_clean(int8_t interface_id, const uint8_t *link_local_address)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return false;
}
bool return_value = false;
#ifndef NO_MLE
mle_neigh_table_entry_t * neigh_entry = mle_class_get_entry_by_ll64(interface_id, 0, link_local_address, false, NULL);
mac_neighbor_table_entry_t *neigh_entry = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), link_local_address, false, NULL);
if (neigh_entry) {
//Remove entry
if (neigh_entry->priorityFlag) {
return_value = true;
} else if (neigh_entry->second_priority_flag) {
if (neigh_entry->link_role == PRIORITY_PARENT_NEIGHBOUR || neigh_entry->link_role == SECONDARY_PARENT_NEIGHBOUR) {
return_value = true;
}
mle_class_remove_entry(interface_id, neigh_entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neigh_entry);
}
#endif
return return_value;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -37,6 +37,7 @@
#include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "mac_api.h"
#ifdef HAVE_RPL
@ -66,6 +67,7 @@
#include "platform/arm_hal_interrupt.h"
#include "common_functions.h"
#include "mac_api.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "libNET/src/net_load_balance_internal.h"
@ -80,12 +82,14 @@ static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur)
/* Change Active -> Idle */
/* Disable Protocols Timers */
if (!thread_info(cur)) {
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
#ifndef NO_MLE
mle_class_list_clean(cur->id);
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
blacklist_clear();
#endif
}
#endif
}
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
pana_reset_values(cur->mac_parameters->pan_id);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -35,13 +35,11 @@ extern struct rpl_domain *protocol_6lowpan_rpl_domain;
extern struct rpl_dodag *protocol_6lowpan_rpl_root_dodag;
#ifdef HAVE_RPL
#ifndef NO_MLE
typedef enum {
PRIORITY_1ST,
PRIORITY_2ND,
} neighbor_priority;
#endif
#endif
void protocol_6lowpan_interface_common_init(struct protocol_interface_info_entry *cur);
void protocol_6lowpan_host_init(struct protocol_interface_info_entry *cur, bool sleepy_host);
@ -53,12 +51,10 @@ int protocol_6lowpan_child_update(struct protocol_interface_info_entry *cur);
void protocol_6lowpan_neighbor_priority_update(struct protocol_interface_info_entry *cur, uint8_t *removed_priority, uint8_t *updated_priority);
#ifdef HAVE_RPL
#ifndef NO_MLE
uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr);
uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr);
void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_priority priority);
#endif
#endif
#else
#define protocol_6lowpan_child_update(cur) (-1)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -27,7 +27,6 @@
struct protocol_interface_info_entry;
struct nd_router;
struct mle_neigh_table_entry_t;
#define MLE_NEIGHBOR_PURGE_NBR 3
#define MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT 4 // Times advertisement timeout

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -77,12 +77,7 @@ buffer_t *lowpan_down(buffer_t *buf)
return NULL;
}
if (thread_info(cur)) {
mle_neigh_table_entry_t *mle_entry;
mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa.address + 2, buf->dst_sa.addr_type);
if (mle_entry && thread_addr_is_child(mac_helper_mac16_address_get(cur), mle_entry->short_adr)) {
/* Check if the child can handle only stable network data (e.g. sleepy device) */
stable_only = !(mle_entry->mode & MLE_THREAD_REQ_FULL_DATA_SET);
}
stable_only = thread_stable_context_check(cur, buf);
}
}
@ -169,7 +164,7 @@ buffer_t *lowpan_down(buffer_t *buf)
/* RFC 6282+4944 require that we limit compression to the first fragment.
* This check is slightly conservative - always allow 4 for first-fragment header
*/
uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf);
uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf);
uint_fast16_t max_iphc_size = mac_helper_max_payload_size(cur, overhead) - mesh_size - 4;
buf = iphc_compress(&cur->lowpan_contexts, buf, max_iphc_size, stable_only);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -45,6 +45,7 @@
#endif
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "mPol"
@ -281,6 +282,23 @@ void mac_poll_timer_trig(uint32_t poll_time, protocol_interface_info_entry_t *cu
}
}
}
static mac_neighbor_table_entry_t *neighbor_data_poll_referesh(protocol_interface_info_entry_t *cur, uint8_t *address, addrtype_t type)
{
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address, type);
if (!entry) {
return NULL;
}
if (!entry->connected_device) {
return NULL;
}
if (!entry->nud_active) {
entry->lifetime = entry->link_lifetime;
}
return entry;
}
void mac_mlme_poll_confirm(protocol_interface_info_entry_t *cur, const mlme_poll_conf_t *confirm)
{
@ -295,20 +313,21 @@ void mac_mlme_poll_confirm(protocol_interface_info_entry_t *cur, const mlme_poll
}
rf_ptr->pollActive = false;
mac_neighbor_table_entry_t *entry = NULL;
switch (confirm->status) {
case MLME_SUCCESS:
//tr_debug("Poll Confirm: Data with Data");
rf_ptr->nwk_parent_poll_fail = 0;
//Trig new Data Poll immediately
mle_refresh_entry_timeout(cur->id, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode, true);
entry = neighbor_data_poll_referesh(cur, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode);
poll_time = 1;
break;
case MLME_NO_DATA:
//Start next case timer
rf_ptr->nwk_parent_poll_fail = 0;
mle_refresh_entry_timeout(cur->id, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode, true);
entry = neighbor_data_poll_referesh(cur, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode);
//tr_debug("Poll Confirm: No Data");
if (rf_ptr->protocol_poll == 0) {
@ -333,6 +352,9 @@ void mac_mlme_poll_confirm(protocol_interface_info_entry_t *cur, const mlme_poll
}
break;
}
if (thread_info(cur) && entry) {
thread_neighbor_communication_update(cur, entry->index);
}
mac_poll_timer_trig(poll_time, cur);
@ -423,7 +445,6 @@ int8_t mac_data_poll_host_mode_set(struct protocol_interface_info_entry *cur, ne
new_poll_time = (poll_time * 1000);
if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
tr_debug("Init Poll timer and period");
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
}
rf_ptr->nwk_app_poll_time = new_poll_time;
@ -449,7 +470,6 @@ int8_t mac_data_poll_host_mode_set(struct protocol_interface_info_entry *cur, ne
}
}
tr_debug("Enable Poll By APP");
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
mac_poll_timer_trig(1, cur);
rf_ptr->nwk_app_poll_time = 300;
@ -525,14 +545,12 @@ void mac_data_poll_init(struct protocol_interface_info_entry *cur)
if (cur->mac_parameters->RxOnWhenIdle) {
tr_debug("Set Non-Sleepy HOST");
rfd_ptr->host_mode = NET_HOST_RX_ON_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
} else {
rfd_ptr->protocol_poll = 1;
mac_poll_timer_trig(200, cur);
tr_debug("Set Sleepy HOST configure");
rfd_ptr->host_mode = NET_HOST_FAST_POLL_MODE;
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
rfd_ptr->slow_poll_rate_seconds = 3;
rfd_ptr->timeOutInSeconds = 32;
rfd_ptr->nwk_app_poll_time = 300;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -25,7 +25,6 @@
#include "net_nwk_scan.h"
#include "ns_trace.h"
#include "common_functions.h"
#include "MLE/mle_tlv.h"
#include "mac_api.h"
#define TRACE_GROUP "MACh"
@ -685,7 +684,7 @@ int8_t mac_helper_mac64_set(protocol_interface_info_entry_t *interface, const ui
* Given a buffer, with address and security flags set, compute the maximum
* MAC payload that could be put in that buffer.
*/
uint_fast16_t mac_helper_max_payload_size(protocol_interface_info_entry_t *cur, uint_fast8_t frame_overhead)
uint_fast16_t mac_helper_max_payload_size(protocol_interface_info_entry_t *cur, uint_fast16_t frame_overhead)
{
uint16_t max;
@ -833,7 +832,17 @@ void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index)
mac_api->mlme_req(mac_api,MLME_SET , &set_req);
}
void mac_helper_devicetable_set(mle_neigh_table_entry_t *entry_temp, protocol_interface_info_entry_t *cur, uint32_t frame_counter, uint8_t keyID, bool force_set)
void mac_helper_device_description_write(protocol_interface_info_entry_t *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt)
{
memcpy(device_desc->ExtAddress, mac64, 8);
device_desc->ShortAddress = mac16;
device_desc->PANId = mac_helper_panid_get(cur);
device_desc->Exempt = exempt;
device_desc->FrameCounter = frame_counter;
}
void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur, uint8_t attribute_index, uint8_t keyID, bool force_set)
{
if (!cur->mac_api) {
return;
@ -844,18 +853,10 @@ void mac_helper_devicetable_set(mle_neigh_table_entry_t *entry_temp, protocol_in
return;
}
mlme_device_descriptor_t device_desc;
mlme_set_t set_req;
device_desc.FrameCounter = frame_counter;
device_desc.Exempt = false;
device_desc.ShortAddress = entry_temp->short_adr;
memcpy(device_desc.ExtAddress, entry_temp->mac64, 8);
device_desc.PANId = mac_helper_panid_get(cur);
set_req.attr = macDeviceTable;
set_req.attr_index = entry_temp->attribute_index;
set_req.value_pointer = (void*)&device_desc;
set_req.attr_index = attribute_index;
set_req.value_pointer = (void*)device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("Register Device");
cur->mac_api->mlme_req(cur->mac_api,MLME_SET , &set_req);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,7 +29,6 @@ struct protocol_interface_info_entry;
struct ns_sockaddr;
struct buffer;
struct mac_api_s;
struct mle_neigh_table_entry_t;
void mac_create_scan_request(mac_scan_type_t type, struct channel_list_s *chanlist, uint8_t scan_duration, struct mlme_scan_s *request);
@ -100,7 +99,7 @@ bool mac_helper_write_our_addr(struct protocol_interface_info_entry *interface,
int8_t mac_helper_mac64_set(struct protocol_interface_info_entry *interface, const uint8_t *mac64);
uint_fast16_t mac_helper_max_payload_size(struct protocol_interface_info_entry *cur, uint_fast8_t frame_overhead);
uint_fast16_t mac_helper_max_payload_size(struct protocol_interface_info_entry *cur, uint_fast16_t frame_overhead);
uint_fast8_t mac_helper_frame_overhead(struct protocol_interface_info_entry *cur, const struct buffer *buf);
@ -110,8 +109,9 @@ int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr);
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index);
void mac_helper_devicetable_set(struct mle_neigh_table_entry_t *entry_temp, struct protocol_interface_info_entry *cur, uint32_t frame_counter, uint8_t keyID, bool force_set);
void mac_helper_device_description_write(struct protocol_interface_info_entry *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt);
void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, struct protocol_interface_info_entry *cur, uint8_t attribute_index, uint8_t keyID, bool force_set);
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);
#endif // MAC_HELPER_H

View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "string.h"
#include "common_functions.h"
#include "mac_common_defines.h"
#include "mac_ie_lib.h"
#define MAC_IE_HEADER_LENGTH_MASK 0x007f
#define MAC_IE_HEADER_ID_MASK 0x7f80
#define MAC_IE_PAYLOAD_LENGTH_MASK 0x07ff
#define MAC_IE_PAYLOAD_ID_MASK 0x7800
#define MAC_IE_TYPE_PAYLOAD_MASK 0x8000
#define MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK 0x07ff
#define MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK 0x7800
#define MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK 0x00ff
#define MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK 0x7f00
#define MAC_NESTED_IE_TYPE_LONG_MASK 0x8000
static void mac_ie_header_parse(mac_header_IE_t *header_element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
header_element->length = (ie_dummy & MAC_IE_HEADER_LENGTH_MASK);
header_element->id = ((ie_dummy & MAC_IE_HEADER_ID_MASK ) >> 7 );
header_element->content_ptr = ptr + 2;
}
static void mac_ie_payload_parse(mac_payload_IE_t *payload_element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
payload_element->length = (ie_dummy & MAC_IE_PAYLOAD_LENGTH_MASK);
payload_element->id = ((ie_dummy & MAC_IE_PAYLOAD_ID_MASK ) >> 11);
payload_element->content_ptr = ptr + 2;
}
static void mac_ie_nested_id_parse(mac_nested_payload_IE_t *element, uint8_t *ptr)
{
uint16_t ie_dummy = common_read_16_bit_inverse(ptr);
if (ie_dummy & MAC_NESTED_IE_TYPE_LONG_MASK) {
element->type_long = true;
element->length = (ie_dummy & MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK);
element->id = ((ie_dummy & MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK ) >> 11);
} else {
element->type_long = false;
element->length = (ie_dummy & MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK);
element->id = ((ie_dummy & MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK ) >> 8);
}
element->content_ptr = ptr + 2;
}
uint8_t *mac_ie_header_base_write(uint8_t *ptr, uint8_t type, uint16_t length)
{
uint16_t ie_dummy = 0; //Header Type
ie_dummy |= (length & MAC_IE_HEADER_LENGTH_MASK);
ie_dummy |= ((type << 7 ) & MAC_IE_HEADER_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_payload_base_write(uint8_t *ptr, uint8_t type, uint16_t length)
{
uint16_t ie_dummy = MAC_IE_TYPE_PAYLOAD_MASK; //Payload type
ie_dummy |= (length & MAC_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((type << 11 ) & MAC_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_nested_ie_long_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length)
{
uint16_t ie_dummy = MAC_NESTED_IE_TYPE_LONG_MASK;
ie_dummy |= (length & MAC_NESTED_LONG_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((sub_id << 11 ) & MAC_NESTED_LONG_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint8_t *mac_ie_nested_ie_short_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length)
{
uint16_t ie_dummy = 0;
ie_dummy |= (length & MAC_NESTED_SHORT_IE_PAYLOAD_LENGTH_MASK);
ie_dummy |= ((sub_id << 8 ) & MAC_NESTED_SHORT_IE_PAYLOAD_ID_MASK);
return common_write_16_bit_inverse(ie_dummy, ptr);
}
uint16_t mac_ie_payload_discover(uint8_t *payload_ptr, uint16_t length, mac_payload_IE_t * payload_ie)
{
mac_payload_IE_t ie_element;
while (length >= 2) {
mac_ie_payload_parse(&ie_element, payload_ptr);
if (payload_ie->id == ie_element.id) {
payload_ie->content_ptr = ie_element.content_ptr;
payload_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint16_t mac_ie_nested_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t * nested_ie)
{
mac_nested_payload_IE_t ie_element;
while (length >= 2) {
mac_ie_nested_id_parse(&ie_element, payload_ptr);
if (length < ie_element.length + 2) {
return 0;
}
if (nested_ie->id == ie_element.id && nested_ie->type_long == ie_element.type_long) {
nested_ie->content_ptr = ie_element.content_ptr;
nested_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
payload_ptr += ie_element.length + 2;
}
return 0;
}
uint8_t mac_ie_header_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t * header_ie)
{
mac_header_IE_t ie_element;
while (length >= 2) {
mac_ie_header_parse(&ie_element, header_ptr);
if (header_ie->id == ie_element.id) {
header_ie->content_ptr = ie_element.content_ptr;
header_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
header_ptr += ie_element.length + 2;
}
return 0;
}
uint8_t mac_ie_header_sub_id_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t * header_ie, uint8_t sub_id)
{
mac_header_IE_t ie_element;
uint8_t *sub_id_ptr;
while (length > 2) {
mac_ie_header_parse(&ie_element, header_ptr);
sub_id_ptr = ie_element.content_ptr;
if (ie_element.length && header_ie->id == ie_element.id && *sub_id_ptr == sub_id) {
sub_id_ptr++;
ie_element.length--;
header_ie->content_ptr = sub_id_ptr;
header_ie->length = ie_element.length;
return ie_element.length;
}
length -= ie_element.length + 2;
header_ptr += ie_element.length + 2;
}
return 0;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MAC_IE_LIB_H_
#define MAC_IE_LIB_H_
struct mac_payload_IE_s;
struct mac_payload_IE_s;
/**
* @brief struct mac_nested_payload_IE_t Mac Nested IE Payload information element structure for parsing or write operation
*/
typedef struct mac_nested_payload_IE_s {
uint8_t *content_ptr; /**< Content data */
uint16_t length; /**< Element length 0- 2047 when type_long true and for short 0- 255*/
unsigned id:7; /**< Group ID 4-bit for long and 7 bit for short type */
bool type_long:1; /**< True when Nested IE long format and false for short */
} mac_nested_payload_IE_t;
/** IE header element generic header write */
uint8_t *mac_ie_header_base_write(uint8_t *ptr, uint8_t type, uint16_t length);
/** IE payload element generic header write */
uint8_t *mac_ie_payload_base_write(uint8_t *ptr, uint8_t type, uint16_t length);
/** Nested IE long header write */
uint8_t *mac_ie_nested_ie_long_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length);
/** Nested IE short header write */
uint8_t *mac_ie_nested_ie_short_base_write(uint8_t *ptr, uint8_t sub_id, uint16_t length);
/** Payload IE discover for spesific group ID */
uint16_t mac_ie_payload_discover(uint8_t *payload_ptr, uint16_t length, struct mac_payload_IE_s * payload_ie);
/** Nested IE element discover inside parsed payload element */
uint16_t mac_ie_nested_discover(uint8_t *payload_ptr, uint16_t length, mac_nested_payload_IE_t * nested_ie);
/** Header IE elemnt discover */
uint8_t mac_ie_header_discover(uint8_t *header_ptr, uint16_t length, struct mac_header_IE_s * header_ie);
/** Header IE elemnt discover with sub id */
uint8_t mac_ie_header_sub_id_discover(uint8_t *header_ptr, uint16_t length, mac_header_IE_t * header_ie, uint8_t sub_id);
#endif /* MAC_IE_LIB_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,6 +29,7 @@
#include "6LoWPAN/MAC/mac_pairwise_key.h"
#include "MLE/mle.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "mPKe"
@ -171,12 +172,12 @@ static mac_pairwise_interface_entry_t *mac_pairwise_key_main_class(uint8_t key_l
static void mac_pairwise_key_list_free(protocol_interface_info_entry_t *interface, mac_pairwise_interface_entry_t *main_list) {
//Delete mle entries & Keys
mle_neigh_table_entry_t *cur_entry;
mac_neighbor_table_entry_t *cur_entry;
mac_pairwise_key_info_t *cur = main_list->mac_pairwise_key_table;
for (uint8_t i = 0; i< main_list->key_table_size; i++) {
cur_entry = mle_class_get_by_device_attribute_id(interface->id, cur->device_descriptor_attribute);
cur_entry = mac_neighbor_table_attribute_discover(mac_neighbor_info(interface), cur->device_descriptor_attribute);
if (cur_entry) {
mle_class_remove_entry(interface->id, cur_entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), cur_entry);
}
mac_helper_security_pairwisekey_set(interface, NULL, NULL, cur->key_decriptor_attribute);
}
@ -266,30 +267,31 @@ int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const ui
}
//Allocate mle entry
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true, &new_entry_created);
if (!mle_entry) {
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, true, &new_entry_created);
if (!mac_entry) {
return -1;
}
mle_entry->thread_commission = true;
mle_entry->short_adr = 0xffff;
mle_entry->ttl = 20;
mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), mac_entry, true);
mac_entry->mac16 = 0xffff;
//Allocate key description
mac_pairwise_key_info_t *key_desc = mac_pairwise_key_info_get(main_list, mle_entry->attribute_index);
mac_pairwise_key_info_t *key_desc = mac_pairwise_key_info_get(main_list, mac_entry->index);
if (!key_desc) {
mle_class_remove_entry(interface_id, mle_entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), mac_entry);
return -1;
}
//Set device descriptor
mac_helper_devicetable_set(mle_entry, interface, 0, interface->mac_parameters->mac_default_key_index, new_entry_created);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(interface, &device_desc, mac_entry->mac64, mac_entry->mac16,0, false);
mac_helper_devicetable_set(&device_desc, interface,mac_entry->index, interface->mac_parameters->mac_default_key_index, new_entry_created);
//set key descriptor
if (mac_helper_security_pairwisekey_set(interface, key, eui64, key_desc->key_decriptor_attribute) != 0) {
main_list->key_table_size--;
mle_class_remove_entry(interface_id, mle_entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), mac_entry);
return -1;
}
@ -309,23 +311,23 @@ int mac_pairwise_key_del(int8_t interface_id, const uint8_t eui64[static 8])
if (!main_list) {
return -1;
}
//Get from mle
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true, NULL);
if (!mle_entry) {
//Get from mac
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, true, NULL);
if (!mac_entry) {
return -1;
}
//discover by mle entry attribute
uint8_t key_attribute;
if (!mac_pairwise_key_info_delete(main_list, mle_entry->attribute_index, &key_attribute)) {
if (!mac_pairwise_key_info_delete(main_list, mac_entry->index, &key_attribute)) {
return -1;
}
//kill Entry & overwrite key
mac_helper_security_pairwisekey_set(interface, NULL, NULL, key_attribute);
mle_class_remove_entry(interface_id, mle_entry);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), mac_entry);
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,9 +31,9 @@
#include "mac_mcps.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/MAC/mac_response_handler.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
static bool mac_data_is_broadcast_addr(const sockaddr_t *addr);
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "MRsH"
@ -49,15 +49,16 @@ static void mac_mlme_device_table_confirmation_handle(protocol_interface_info_en
if (confirmation->status == MLME_SUCCESS) {
//GET ME table by extended mac64 address
mle_neigh_table_entry_t * entry = mle_class_get_by_link_address(info_entry->id, descpription->ExtAddress, ADDR_802_15_4_LONG);
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(info_entry), descpription->ExtAddress, ADDR_802_15_4_LONG);
if (!entry) {
return;
}
if (entry->short_adr != descpription->ShortAddress) {
if (entry->mac16 != descpription->ShortAddress) {
//Refresh Short ADDRESS
mlme_set_t set_request;
descpription->ShortAddress = entry->short_adr;
descpription->ShortAddress = entry->mac16;
//CALL MLME-SET
set_request.attr = macDeviceTable;
@ -107,62 +108,10 @@ void mcps_data_confirm_handler( const mac_api_t* api, const mcps_data_conf_t *da
lowpan_adaptation_interface_tx_confirm(info_entry, data);
}
static bool mcps_data_indication_neighbor_validate(int8_t interface_id, const sockaddr_t *addr)
{
/* If MLE is enabled, we will talk if we have an MLE association */
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(interface_id, addr->address + 2, addr->addr_type);
if (mle_entry && (mle_entry->handshakeReady || mle_entry->thread_commission)) {
return true;
}
/* Otherwise, we don't know them */
return false;
}
void mcps_data_indication_handler( const mac_api_t* api, const mcps_data_ind_t *data_ind )
{
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
buffer_t *buf = buffer_get(data_ind->msduLength);
if (!buf || !info_entry) {
return;
}
uint8_t *ptr;
buffer_data_add(buf, data_ind->msdu_ptr, data_ind->msduLength);
//tr_debug("MAC Paylod size %u %s",data_ind->msduLength, trace_array(data_ind->msdu_ptr, 8));
buf->options.lqi = data_ind->mpduLinkQuality;
buf->options.dbm = data_ind->signal_dbm;
buf->src_sa.addr_type = (addrtype_t)data_ind->SrcAddrMode;
ptr = common_write_16_bit(data_ind->SrcPANId, buf->src_sa.address);
memcpy(ptr, data_ind->SrcAddr, 8);
buf->dst_sa.addr_type = (addrtype_t)data_ind->DstAddrMode;
ptr = common_write_16_bit(data_ind->DstPANId, buf->dst_sa.address);
memcpy(ptr, data_ind->DstAddr, 8);
//Set Link spesific stuff to seperately
buf->link_specific.ieee802_15_4.srcPanId = data_ind->SrcPANId;
buf->link_specific.ieee802_15_4.dstPanId = data_ind->DstPANId;
if (mac_data_is_broadcast_addr(&buf->dst_sa)) {
buf->options.ll_broadcast_rx = true;
}
buf->interface = info_entry;
if (data_ind->Key.SecurityLevel) {
buf->link_specific.ieee802_15_4.fc_security = true;
if (info_entry->mac_security_key_usage_update_cb) {
info_entry->mac_security_key_usage_update_cb(info_entry, &data_ind->Key);
}
} else {
buf->link_specific.ieee802_15_4.fc_security = false;
if (mac_helper_default_security_level_get(info_entry) ||
!mcps_data_indication_neighbor_validate(info_entry->id, &buf->src_sa)) {
//SET By Pass
buf->options.ll_security_bypass_rx = true;
}
}
buf->info = (buffer_info_t)(B_TO_IPV6_TXRX | B_FROM_MAC | B_DIR_UP);
protocol_push(buf);
lowpan_adaptation_interface_data_ind(info_entry, data_ind);
}
void mcps_purge_confirm_handler( const mac_api_t* api, mcps_purge_conf_t *data )
@ -306,9 +255,3 @@ void mlme_indication_handler( const mac_api_t* api, mlme_primitive id, const voi
}
}
bool mac_data_is_broadcast_addr(const sockaddr_t *addr)
{
return (addr->addr_type == ADDR_802_15_4_SHORT) &&
(addr->address[2] == 0xFF && addr->address[3] == 0xFF);
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MPX_API_H_
#define MPX_API_H_
struct mcps_data_req_s;
struct mcps_data_conf_s;
struct mcps_data_ind_s;
struct mcps_purge_s;
typedef struct mpx_api_s mpx_api_t;
/**
* @brief mpx_data_request MPX_DATA request with user ID
* @param api API to handle the request
* @param data MCPS-DATA.request specific values
* @param user_id MPX user ID
*
*/
typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id);
/**
* @brief mpx_data_queue_clean clean MPX user data
* @param api API to handle the request
* @param purge MCPS-purge request
* @param user_id MPX user ID
*
*/
typedef void mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
/**
* @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request
* @param api The API which handled the response
* @param data MCPS-DATA.confirm specific values
* @param user_id MPX user ID
*/
typedef void mpx_data_confirm(const mpx_api_t* api, const struct mcps_data_conf_s *data);
/**
* @brief mpx_data_indication MPX-DATA confirm is called as a response to MPX-DATA request
* @param api The API which handled the response
* @param data MCPS-DATA.indication specific values
* @param user_id MPX user ID
*/
typedef void mpx_data_indication(const mpx_api_t* api, const struct mcps_data_ind_s *data);
/**
* @brief mpx_header_size_get Function for request MPX user head room size
* @param api The API which handled the response
* @param user_id MPX user ID
*
* @return >0 Head room size in bytes
* @return 0 When Unknown User Id
*/
typedef uint16_t mpx_header_size_get(const mpx_api_t * api, uint16_t user_id);
/**
* @brief mpx_data_cb_register MPX-DATA confirm cb register by user
* @param api The API which handled the response
* @param confirm_cb MPX Data Confirm call back
* @param indication_cb MPX Data indication
* @param user_id MPX user ID
*
* @return 0 register OK
* @return -1 Unknown User ID
*/
typedef int8_t mpx_data_cb_register(const mpx_api_t* api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id);
/**
* \brief Struct mpx_api_s defines functions for MPX user for register call backs and send data.
*/
struct mpx_api_s {
mpx_data_request * mpx_data_request; /**< MPX data request. */
mpx_data_purge_request *mpx_data_purge; /**< MPX data Purge. */
mpx_header_size_get * mpx_headroom_size_get; /**< MPX headroom size get in bytes. */
mpx_data_cb_register * mpx_user_registration; /**< MPX User cb registration must be call before enable to send or RX data*/
};
#endif /* MPX_API_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -41,6 +41,8 @@
#include "BorderRouter/border_router.h"
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/ws/ws_common.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "loND"
@ -845,17 +847,18 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
/* Register with 2 seconds off the lifetime - don't want the NCE to expire before the route */
ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, neigh->lifetime - 2, 0);
#ifndef NO_MLE
/* We need to know peer is a host before publishing - this needs MLE. Not yet established
* what to do without MLE - might need special external/non-external prioritisation at root.
* This "publish for RFD" rule comes from ZigBee IP.
*/
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur_interface->id, ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh), ADDR_802_15_4_LONG);
if (mle_entry && ((mle_entry->mode & MLE_DEV_MASK) == MLE_RFD_DEV)) {
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur_interface), ipv6_neighbour_eui64(&cur_interface->ipv6_neighbour_cache, neigh), ADDR_802_15_4_LONG);
if (entry && !entry->ffd_device) {
rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime);
}
protocol_6lowpan_neighbor_address_state_synch(cur_interface, aro->eui64, neigh->ip_address + 8);
#endif
} else {
/* Um, no - can't transmit response if we remove NCE now! */
//ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache, neigh);
@ -863,9 +866,7 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac
neigh->lifetime = 2;
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, 4, 0);
#ifndef NO_MLE
rpl_control_unpublish_address(protocol_6lowpan_rpl_domain, neigh->ip_address);
#endif
}
}
@ -967,7 +968,13 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
/* Set the LL address, ensure it's marked STALE */
ipv6_neighbour_entry_update_unsolicited(&cur_interface->ipv6_neighbour_cache, neigh, ll_addr.addr_type, ll_addr.address);
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
if (ws_info(cur_interface)) {
aro_out->status = ARO_SUCCESS;
aro_out->present = true;
// Todo: this might not be needed...
nd_update_registration(cur_interface, neigh, aro_out);
return true;
}
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || nd_params.multihop_dad == false) {
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
whiteboard_entry_t *wb;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -30,10 +30,23 @@
#ifndef THREAD_ADDRESS_REGISTRATION_CLIENT_H_
#define THREAD_ADDRESS_REGISTRATION_CLIENT_H_
#ifdef HAVE_THREAD_V2
void thread_address_registration_init(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_deinit(void)
#define thread_address_registration_timer_set(interface, seconds);
#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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -943,7 +943,7 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t seconds)
#endif // HAVE_THREAD_ROUTER
#ifdef HAVE_THREAD_BORDER_ROUTER
static int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
@ -955,18 +955,18 @@ static int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 1
return 0;
}
int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info, const uint8_t *mleid_ptr) {
(void) mleid_ptr;
int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info)
{
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
if (!this || this->backbone_interface_id < 0) {
tr_err("bbr not ready");
return -1;
}
ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_HOST, info, 0, lifetime, 0);
// We are using route info field to store sequence number
if (!route) {
// Direct route to host allows ND proxying to work
tr_err("out of resources");
tr_err("bbr out of resources");
return -2;
}
// send NA
@ -975,14 +975,44 @@ int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,
return 0;
}
int thread_bbr_nd_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_HOST ) {
//Not found
int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr)
{
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
if (!this || this->backbone_interface_id < 0) {
return -1;
}
//TODO get information to route to parameters eq mleid, timeout
thread_pbbr_dua_info_t *map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t));
if (!map) {
goto error;
}
memcpy(map->mleid_ptr, mleid_ptr, 8);
map->last_contact_time = protocol_core_monotonic_time;
// We are using route info field to store BBR MLEID map
ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0);
if (!route) {
// Direct route to host allows ND proxying to work
ns_dyn_mem_free(map);
goto error;
}
// Route info autofreed
route->info_autofree = true;
// send NA
thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr);
return 0;
error:
tr_err("out of resources");
return -2;
}
struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST ) {
//Not found
return NULL;
}
return route;
}
int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status)
@ -1090,6 +1120,17 @@ return 0;
#endif // HAVE_THREAD_BORDER_ROUTER
}
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);
#else
return -1;
#endif // HAVE_THREAD_BORDER_ROUTER
}
int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port)
{
(void) interface_id;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -36,6 +36,8 @@
#include "net_interface.h"
#ifdef HAVE_THREAD_ROUTER
struct ipv6_route;
/**
* \brief Initialize Thread Commissioner relay for BBR and Routers
*
@ -98,23 +100,39 @@ void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
/**
* \brief Add new nd entry to bbr
*
* \param interface_id addr_data_ptr lifetime info mleid_ptr
* \param interface_id addr_data_ptr lifetime info
*/
int thread_bbr_nd_entry_add(int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info, const uint8_t *mleid_ptr);
int thread_bbr_nd_entry_add(int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, void *info);
/**
* \brief Find if bbr has nd entry
* \brief Add new dua entry to bbr
*
* \param interface_id addr_data_ptr lifetime info mleid_ptr
*/
int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr);
/**
* \brief Send na
*
* \param interface_id addr_data_ptr lifetime info mleid_ptr
*/
int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16]);
/**
* \brief Find if bbr has dua entry
*
* \param interface_id addr_data_ptr
*/
int thread_bbr_nd_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr);
struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr);
#else
#define thread_bbr_proxy_state_update(caller_interface_id , handler_interface_id, status) (NULL)
#define thread_bbr_routing_enabled(cur) false
#define thread_bbr_network_data_update_notify(cur)
#define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info, mleid_ptr) (0)
#define thread_bbr_nd_entry_find(interface_id, addr_data_ptr) (0)
#define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info) (0)
#define thread_bbr_dua_entry_add(interface_id, addr_data_ptr, lifetime, mleid_ptr) (0)
#define thread_bbr_dua_entry_find(interface_id, addr_data_ptr) (NULL)
#define thread_bbr_na_send(interface_id, target) (0)
#endif //HAVE_THREAD_BORDER_ROUTER

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -59,6 +59,7 @@
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
#include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/Thread/thread_management_server.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h"
#include "6LoWPAN/Thread/thread_network_synch.h"
#include "6LoWPAN/Thread/thread_joiner_application.h"
@ -90,9 +91,14 @@
#include "thread_meshcop_lib.h"
#include "multicast_api.h"
#include "mlme.h"
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "Service_Libs/mle_service/mle_service_api.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "platform/topo_trace.h"
#define TRACE_GROUP "thbs"
@ -111,27 +117,46 @@ static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_en
static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state);
static void thread_bootsrap_network_discovery_failure(int8_t interface_id);
static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur);
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);
static bool thread_interface_is_active(int8_t interface_id) {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
{
protocol_interface_info_entry_t *cur = user_data;
lowpan_adaptation_remove_free_indirect_table(cur, entry_ptr);
thread_reset_neighbour_info(cur, entry_ptr);
//Removes ETX neighbor
etx_neighbor_remove(cur->id, entry_ptr->index);
//Remove MLE frame counter info
mle_service_frame_counter_entry_delete(cur->id, entry_ptr->index);
}
static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
{
// Sleepy host
protocol_interface_info_entry_t *cur_interface = user_data;
if (thread_am_router(cur_interface)) {
return false; //Never do Keep alive with any one
}
if (entry_ptr->link_role != PRIORITY_PARENT_NEIGHBOUR) {
return false; //Do not never challenge than priority parent
}
if (cur_interface->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
return false; //Sleepy end device should not never challenge
}
if (entry_ptr->lifetime > MLE_TABLE_CHALLENGE_TIMER) {
return false;
}
return true;
}
static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur)
{
protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur_interface) {
return;
}
thread_reset_neighbour_info(cur_interface, cur);
return thread_host_bootstrap_child_update(cur_interface, entry_ptr->mac64);
}
int8_t thread_mle_class_init(int8_t interface_id)
@ -151,11 +176,29 @@ int8_t thread_mle_class_init(int8_t interface_id)
return -1;
}
if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_host_bootstrap_child_update, &thread_interface_is_active) != 0) {
thread_neighbor_class_delete(&cur->thread_info->neighbor_class);
if (!thread_neighbor_class_create(&cur->thread_info->neighbor_class, buffer.device_decription_table_size - 1)) {
return -1;
}
mle_class_router_challenge(interface_id, NULL);
if (!mac_neighbor_info(cur) ) {
mac_neighbor_info(cur) = mac_neighbor_table_create(buffer.device_decription_table_size - 1, thread_neighbor_remove
, thread_neighbor_entry_nud_notify, cur);
if (!mac_neighbor_info(cur)) {
return -1;
}
}
if (mle_service_frame_counter_table_allocate(interface_id, buffer.device_decription_table_size - 1)) {
return -1;
}
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size - 1)) {
return -1;
}
lowpan_adaptation_interface_etx_update_enable(cur->id);
//Defined well know neighbour for discovery
@ -232,7 +275,7 @@ uint8_t thread_calculate_link_margin(int8_t dbm, uint8_t compLinkMarginFromParen
return newLqi;
}
bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp)
bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_temp)
{
if (entry_temp && thread_info(cur)->thread_endnode_parent) {
if(memcmp(entry_temp->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) == 0) {
@ -245,45 +288,31 @@ bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mle_ne
bool thread_bootstrap_request_network_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, uint16_t short_address)
{
bool requestNetworkdata = false;
thread_leader_data_t *leadeInfo = thread_info(cur)->thread_leader_data;
thread_leader_data_t *leaderInfo = thread_info(cur)->thread_leader_data;
if (thread_info(cur)->thread_endnode_parent->shortAddress != short_address) {
return false;
}
if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) {
if (!thread_partition_match(cur, leaderData)) {
tr_debug("Learn new Network Data");
requestNetworkdata = true;
thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1;
thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1;
thread_partition_info_update(cur, leaderData);
}
else if (common_serial_number_greater_8(leaderData->dataVersion, leadeInfo->dataVersion)) {
else if (common_serial_number_greater_8(leaderData->dataVersion, leaderInfo->dataVersion)) {
requestNetworkdata = true;
} else if (common_serial_number_greater_8(leaderData->stableDataVersion, leadeInfo->stableDataVersion)) {
} else if (common_serial_number_greater_8(leaderData->stableDataVersion, leaderInfo->stableDataVersion)) {
requestNetworkdata = true;
}
// Version number is updated when new network data is learned to avoid synchronization problems
thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId;
thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId;
if (requestNetworkdata) {
thread_bootstrap_parent_network_data_request(cur, true);
}
return true;
}
bool thread_instance_id_matches(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
{
if (thread_info(cur)->thread_leader_data) {
if (thread_info(cur)->thread_leader_data->partitionId == leaderData->partitionId) {
return true;
}
}
return false;
}
static int thread_router_check_previous_partition_info(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv)
{
if (!routeTlv || !routeTlv->dataPtr || !routeTlv->tlvLen || !leaderData) {
@ -386,8 +415,7 @@ int thread_leader_data_validation(protocol_interface_info_entry_t *cur, thread_l
if (!thread_info(cur)->thread_leader_data) {
return -1;
}
if ((thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) ||
(thread_info(cur)->thread_leader_data->weighting != leaderData->weighting)) {
if (!thread_partition_match(cur, leaderData)) {
uint8_t routers_in_route_tlv = thread_get_router_count_from_route_tlv(routeTlv);
//partition checks
return thread_bootstrap_partition_process(cur,routers_in_route_tlv,leaderData, routeTlv);
@ -472,11 +500,9 @@ void thread_end_device_mode_set(protocol_interface_info_entry_t *cur, bool sleep
{
if (sleepy) {
cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
} else {
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
}
}
@ -537,9 +563,6 @@ void thread_set_link_local_address(protocol_interface_info_entry_t *cur)
static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration)
{
uint8_t key_material[32];
uint8_t key_index;
tr_debug("MAC SET Security Mode");
if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE) || !(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) {
@ -554,15 +577,10 @@ static int thread_configuration_security_activate(protocol_interface_info_entry_
cur->thread_info->masterSecretMaterial.historyKeyValid = false;
cur->thread_info->masterSecretMaterial.valid_Info = true;
// Update the guard timer value
thread_calculate_key_guard_timer(cur, linkConfiguration, true);
thread_key_guard_timer_calculate(cur, linkConfiguration, true);
//Define KEY's
thread_key_get(linkConfiguration->master_key, key_material, linkConfiguration->key_sequence);
key_index = THREAD_KEY_INDEX(linkConfiguration->key_sequence);
//Set Keys
mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
//Add Security to MLE service
mle_service_security_set_security_key(cur->id, key_material, key_index, true);
//Gen also Next Key
thread_security_prev_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
thread_security_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
thread_security_next_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
return 0;
}
@ -711,9 +729,9 @@ int thread_configuration_mle_disable(protocol_interface_info_entry_t *cur)
return 0;
}
int thread_mle_service_register(int8_t interface_id, uint8_t *mac64 )
static int thread_mle_service_register(protocol_interface_info_entry_t *cur, uint8_t *mac64 )
{
if (mle_service_interface_register(interface_id,thread_mle_parent_discover_receive_cb, mac64,8) != 0) {
if (mle_service_interface_register(cur->id, cur, thread_mle_parent_discover_receive_cb, mac64,8) != 0) {
tr_error("Mle Service init Fail");
return -1;
}
@ -1052,7 +1070,7 @@ void thread_tasklet(arm_event_s *event)
case THREAD_CHILD_UPDATE:
tr_debug_extra("Thread SM THREAD_CHILD_UPDATE");
if (thread_info(cur)->thread_endnode_parent) {
thread_host_bootstrap_child_update(cur->id, cur->thread_info->thread_endnode_parent->mac64);
thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64);
}
break;
case THREAD_ANNOUNCE_ACTIVE: {
@ -1166,12 +1184,12 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur)
void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur)
{
mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach_safe(mle_neigh_table_entry_t, cur_entry, neig_list) {
if (!thread_addr_is_equal_or_child(cur->thread_info->routerShortAddress, cur_entry->short_adr)) {
tr_debug("Free ID %x", cur_entry->short_adr);
mle_class_remove_entry(cur->id, cur_entry);
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (!thread_addr_is_equal_or_child(cur->thread_info->routerShortAddress, cur_entry->mac16)) {
tr_debug("Free ID %x", cur_entry->mac16);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry);
}
}
}
@ -1454,9 +1472,7 @@ int thread_bootstrap_reset(protocol_interface_info_entry_t *cur)
neighbor_cache_flush(&cur->neigh_cache);
thread_bootstrap_stop(cur);
#ifndef NO_MLE
mle_class_list_clean(cur->id);
#endif
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
cur->bootsrap_state_machine_cnt = 0;
mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params);
//tr_debug( "--> idle");
@ -1600,6 +1616,7 @@ void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur)
// FEDs and routers (REEDs) perform their own address resolution
thread_nd_service_activate(cur->id);
} else {
thread_nd_client_service_activate(cur->id);
thread_child_set_default_route(cur);
}
}
@ -2177,7 +2194,7 @@ void thread_bootstrap_start_network_discovery(protocol_interface_info_entry_t *c
scan_request.channel_mask = cur->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0];
scan_request.filter_tlv_data = NULL;
scan_request.filter_tlv_length = 0;
if (thread_discovery_network_scan(cur->id, &scan_request, discover_ready) != 0 ) {
if (thread_discovery_network_scan(cur, &scan_request, discover_ready) != 0 ) {
tr_error("Discovery scan start fail");
}
}
@ -2198,7 +2215,7 @@ void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
//SET Link by Static configuration
tr_info("thread network attach start");
if (thread_mle_service_register(cur->id,thread_joiner_application_random_mac_get(cur->id)) != 0 ||
if (thread_mle_service_register(cur,thread_joiner_application_random_mac_get(cur->id)) != 0 ||
thread_link_configuration_activate(cur, linkConfiguration) != 0) {
tr_error("Network Bootsrap Start Fail");
bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, cur);
@ -2257,6 +2274,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
thread_leader_service_leader_data_free(cur->thread_info);
thread_bootstrap_all_nodes_multicast_unregister(cur);
thread_data_base_init(cur->thread_info, cur->id);
@ -2672,7 +2690,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_joiner_router_init(cur->id);
thread_extension_service_init(cur);
// Update border router relay
thread_bbr_commissioner_proxy_service_update(cur->id);
@ -2870,8 +2888,7 @@ void thread_bootstrap_clear_neighbor_entries(protocol_interface_info_entry_t *cu
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour);
}
}
mle_class_list_clean(cur->id);
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
}
void thread_bootstrap_dynamic_configuration_save(protocol_interface_info_entry_t *cur)
@ -2883,10 +2900,10 @@ void thread_bootstrap_dynamic_configuration_save(protocol_interface_info_entry_t
if (thread_i_am_router(cur)) {
/* Store information of our children to the dynamic storage */
mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id);
ns_list_foreach_safe(mle_neigh_table_entry_t, entry, neig_list) {
if (thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->short_adr)) {
thread_dynamic_storage_child_info_store(cur->id, entry);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach_safe(mac_neighbor_table_entry_t, entry, mac_table_list) {
if (thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->mac16)) {
thread_dynamic_storage_child_info_store(cur, entry);
}
}
}
@ -2910,7 +2927,7 @@ bool thread_bootstrap_link_create_check(protocol_interface_info_entry_t *interfa
return false;
}
if(mle_class_free_entry_count_get(interface->id) < 1) {
if(mle_class_free_entry_count_get(interface) < 1) {
// We dont have room for any new links
tr_warn("Link ignore no room for addr:%x", short_address);
return false;
@ -2928,7 +2945,7 @@ bool thread_bootstrap_link_create_check(protocol_interface_info_entry_t *interfa
return false;
}
if (mle_class_active_neigh_counter(interface->id) < THREAD_REED_AND_END_DEVICE_NEIGHBOR_LINKS + 1) {
if (mle_class_active_neigh_counter(interface) < THREAD_REED_AND_END_DEVICE_NEIGHBOR_LINKS + 1) {
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -52,7 +52,7 @@ struct thread_info_s;
struct protocol_interface_info_entry;
struct thread_leader_data_s;
struct link_configuration;
struct mle_neigh_table_entry_t;
struct mac_neighbor_table_entry;
struct mle_tlv_info_s;
typedef enum {
@ -103,12 +103,11 @@ uint8_t thread_mode_get_by_interface_ptr(struct protocol_interface_info_entry *c
void thread_bootstrap_device_synch_finish(protocol_interface_info_entry_t *cur);
int8_t thread_mle_class_init(int8_t interface_id);
void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
int thread_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mle_neigh_table_entry_t *child);
void thread_bootstrap_ready(struct protocol_interface_info_entry *cur);
int thread_bootstrap_reset(struct protocol_interface_info_entry *cur);
void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur);
bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address);
bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mle_neigh_table_entry_t *entry_temp);
bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mac_neighbor_table_entry *entry_temp);
void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur);
int8_t thread_bootsrap_event_trig(thread_bootsrap_event_type_e event_type, int8_t Id, arm_library_event_priority_e priority);
void thread_interface_init(struct protocol_interface_info_entry *cur);
@ -126,7 +125,6 @@ int thread_parent_discover_start(int8_t interface_id, uint8_t *mac64 );
bool thread_device_synch_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
bool thread_link_request_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
bool thread_instance_id_matches(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData);
int thread_leader_data_validation(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, struct mle_tlv_info_s *routeTlv);
uint8_t thread_calculate_link_margin(int8_t dbm, uint8_t compLinkMarginFromParent);
uint8_t thread_compute_link_margin(int8_t rssi);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -297,19 +297,19 @@ static bool thread_border_router_local_network_data_prefix_match(thread_network_
return true;
}
static void thread_border_router_child_network_data_clean(uint8_t interface_id, uint16_t child_id)
static void thread_border_router_child_network_data_clean(protocol_interface_info_entry_t *cur, uint16_t child_id)
{
uint8_t addr16_buf[2];
common_write_16_bit(child_id, addr16_buf);
if (mle_class_get_by_link_address(interface_id, addr16_buf, ADDR_802_15_4_SHORT)) {
if (mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr16_buf, ADDR_802_15_4_SHORT)) {
/* Child is available in mle, do nothing */
return;
}
// Child is not our child => network data contains data from lost children, remove it
tr_debug("Remove nwk data from lost child: %04x", child_id);
thread_management_client_network_data_unregister(interface_id, child_id);
thread_management_client_network_data_unregister(cur->id, child_id);
}
static void thread_border_router_lost_children_nwk_data_validate(protocol_interface_info_entry_t *cur, uint16_t router_short_addr)
@ -326,7 +326,7 @@ static void thread_border_router_lost_children_nwk_data_validate(protocol_interf
ns_list_foreach(thread_network_server_data_entry_t, curRoute, &curLP->routeList) {
if (thread_addr_is_child(router_short_addr, curRoute->routerID)) {
// Router children found
thread_border_router_child_network_data_clean(cur->id, curRoute->routerID);
thread_border_router_child_network_data_clean(cur, curRoute->routerID);
}
}
@ -334,7 +334,7 @@ static void thread_border_router_lost_children_nwk_data_validate(protocol_interf
ns_list_foreach(thread_network_server_data_entry_t, curBR, &curLP->borderRouterList) {
if (thread_addr_is_child(router_short_addr, curBR->routerID)) {
// Router children found
thread_border_router_child_network_data_clean(cur->id, curBR->routerID);
thread_border_router_child_network_data_clean(cur, curBR->routerID);
}
}
}
@ -344,7 +344,7 @@ static void thread_border_router_lost_children_nwk_data_validate(protocol_interf
ns_list_foreach(thread_network_data_service_server_entry_t, server, &service->server_list) {
if (thread_addr_is_child(router_short_addr, server->router_id)) {
// Router children found
thread_border_router_child_network_data_clean(cur->id, server->router_id);
thread_border_router_child_network_data_clean(cur, server->router_id);
}
}
}
@ -626,6 +626,7 @@ int thread_border_router_prefix_add(int8_t interface_id, uint8_t *prefix_ptr, ui
service.stableData = prefix_info_ptr->stableData;
service.P_on_mesh = prefix_info_ptr->P_on_mesh;
service.P_nd_dns = prefix_info_ptr->P_nd_dns;
service.P_res1 = prefix_info_ptr->P_res1;
return thread_local_server_list_add_on_mesh_server(&cur->thread_info->localServerDataBase, &prefixTlv, &service);
#else

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2015, 2017, Arm Limited and affiliates.
* Copyright (c) 2014-2015, 2017-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -64,6 +64,7 @@
#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_neighbor_class.h"
#include "MLE/mle.h"
#include "Service_Libs/mle_service/mle_service_security.h"
#include "Service_Libs/blacklist/blacklist.h"
@ -79,6 +80,7 @@
#include "MLE/mle_tlv.h"
#include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/mle_service/mle_service_api.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_pairwise_key.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
@ -104,7 +106,7 @@ thread_leader_data_t *thread_leader_data_generate(void);
thread_parent_info_t *thread_parent_data_allocate(thread_info_t *info);
static uint8_t * thread_joining_port_tlv_write(uint16_t port, uint8_t *ptr);
static uint8_t * thread_commissioner_port_tlv_write(uint16_t port, uint8_t *ptr);
static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, mle_neigh_table_entry_t *neighbor);
static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, uint8_t attribute_index);
static void thread_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason);
/* Helper functions*/
@ -152,10 +154,15 @@ uint8_t *thread_management_key_request_with_sequence(int8_t interface_id, uint8_
if (!linkConfiguration) {
return NULL;
}
//tr_debug("MLE key request by sequence id %"PRIu8" seq %"PRIu32, keyId, keySequnce);
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur && cur->thread_info) {
if (cur->thread_info->masterSecretMaterial.valid_Info) {
if (!cur || !cur->thread_info) {
return NULL;
}
if (!cur->thread_info->masterSecretMaterial.valid_Info) {
return NULL;
}
if (keySequnce == linkConfiguration->key_sequence) {
if (mle_service_security_default_key_id_get(interface_id) == keyId) {
keyPtr = mle_service_security_default_key_get(interface_id);
@ -173,12 +180,11 @@ uint8_t *thread_management_key_request_with_sequence(int8_t interface_id, uint8_
cur->thread_info->masterSecretMaterial.historyKeyValid = false;
keyPtr = cur->thread_info->masterSecretMaterial.historyKey;
}
}
}
return keyPtr;
}
uint8_t * thread_mle_service_security_notify_cb(int8_t interface_id, mle_security_event_t event, uint8_t keyId)
{
(void)keyId;
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return NULL;
@ -197,7 +203,7 @@ uint8_t * thread_mle_service_security_notify_cb(int8_t interface_id, mle_securit
break;
case MLE_SEC_UNKNOWN_KEY:
return thread_management_key_request(interface_id,keyId);
return NULL;
}
return NULL;
}
@ -360,23 +366,31 @@ bool thread_connectivity_tlv_parse(uint8_t *ptr, uint16_t dataLength, thread_con
return false;
}
void thread_calculate_key_guard_timer(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, bool is_init)
void thread_key_guard_timer_calculate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, bool is_init)
{
uint32_t key_rotation = linkConfiguration ? linkConfiguration->key_rotation : 0;
if (is_init && key_rotation < 3600) {
if (is_init && key_rotation < 1) {
tr_warn("Attempted to set key rotation time smaller than 1 hour.");
key_rotation = 3600;
key_rotation = 1;
}
cur->thread_info->masterSecretMaterial.keyRotation = key_rotation;
cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = is_init ? 0 : (key_rotation * 0.93);
cur->thread_info->masterSecretMaterial.keyRotation = key_rotation * 3600; // setting value is hours converting to seconds
cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = is_init ? 0 : (key_rotation * 3600 * 0.93);
}
void thread_key_guard_timer_reset(protocol_interface_info_entry_t *cur)
{
cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = 0;
}
thread_leader_data_t *thread_leader_data_generate(void)
{
thread_leader_data_t *leader_data;
leader_data = ns_dyn_mem_alloc(sizeof(thread_leader_data_t));
if (leader_data) {
memset(leader_data,0,sizeof(thread_leader_data_t));
}
return leader_data;
}
@ -663,16 +677,27 @@ thread_mcast_child_t *thread_child_mcast_entry_find(thread_mcast_children_list_t
return NULL;
}
bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf)
{
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur),buf->dst_sa.address + 2 , buf->dst_sa.addr_type);
if (entry && thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->mac16)) {
/* Check if the child can handle only stable network data (e.g. sleepy device) */
return !(thread_neighbor_class_request_full_data_setup(&cur->thread_info->neighbor_class, entry->index));
}
return false;
}
thread_mcast_child_t *thread_child_mcast_entry_get(protocol_interface_info_entry_t *cur, const uint8_t *mcast_addr, const uint8_t *mac64)
{
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, mac64, ADDR_802_15_4_LONG);
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), mac64, ADDR_802_15_4_LONG);
if (!mle_entry) {
if (!entry) {
tr_error("No MLE entry.");
return NULL;
}
if (mle_entry->mode & MLE_RX_ON_IDLE) {
if (entry->rx_on_idle) {
/* Not a sleepy child */
tr_debug("Not a sleepy child");
return NULL;
@ -791,8 +816,6 @@ int thread_init(protocol_interface_info_entry_t *cur)
return -1;
}
mle_class_router_challenge(cur->id, NULL);
if (etx_accum_failures_callback_register(cur->nwk_id, cur->id, 1, thread_tx_failure_handler) != 1) {
return -1;
}
@ -803,7 +826,6 @@ int thread_init(protocol_interface_info_entry_t *cur)
thread_data_base_init(cur->thread_info, cur->id);
mac_helper_pib_boolean_set(cur,macThreadForceLongAddressForBeacon , true);
mac_helper_mac16_address_set(cur, 0xffff);
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
return 0;
}
@ -817,7 +839,7 @@ int thread_attach_ready(protocol_interface_info_entry_t *cur)
case THREAD_STATE_CONNECTED:
case THREAD_STATE_CONNECTED_ROUTER:
return 0;
break;
/* break; */
default:
break;
}
@ -919,7 +941,7 @@ static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16
tr_debug("thrKeyRotation == 0: sync key material by %"PRIu32, linkConfiguration->key_sequence + 1);
thread_management_key_sets_calc(cur, linkConfiguration, linkConfiguration->key_sequence + 1);
thread_calculate_key_guard_timer(cur, linkConfiguration, false);
thread_key_guard_timer_calculate(cur, linkConfiguration, false);
}
}
@ -1019,14 +1041,15 @@ void thread_timer(protocol_interface_info_entry_t *cur, uint8_t ticks)
return;
}
if (thread_i_am_router(cur)) {
if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
/* Own attach is ongoing, do not send advertisements */
return;
}
if (thread_i_am_router(cur)) {
if (thread_routing_timer(thread_info, ticks)) {
thread_router_bootstrap_mle_advertise(cur);
}
} else {
}
}
@ -1121,14 +1144,20 @@ uint8_t thread_beacon_indication(uint8_t *ptr, uint8_t len, protocol_interface_i
static uint8_t *thread_linkquality_write(int8_t interface_id, uint8_t *buffer)
{
protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface_ptr && !interface_ptr->thread_info) {
return buffer;
}
uint8_t lqi1 = 0, lqi2 = 0, lqi3 = 0;
thread_link_quality_e thread_link_quality;
mle_neigh_table_list_t *neigh_list = mle_class_active_list_get(interface_id);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(interface_ptr)->neighbour_list;
ns_list_foreach(mle_neigh_table_entry_t, cur, neigh_list) {
if (thread_is_router_addr(cur->short_adr)) {
ns_list_foreach(mac_neighbor_table_entry_t, cur, mac_table_list) {
if (thread_is_router_addr(cur->mac16)) {
// Only count routers to link quality
thread_link_quality = thread_link_margin_to_quality(cur->link_margin);
uint16_t link_margin = thread_neighbor_entry_linkmargin_get(&interface_ptr->thread_info->neighbor_class, cur->index);
thread_link_quality = thread_link_margin_to_quality(link_margin);
switch (thread_link_quality) {
case QUALITY_20dB:
lqi3++;
@ -1193,14 +1222,14 @@ uint8_t *thread_connectivity_tlv_write(uint8_t *ptr, protocol_interface_info_ent
*ptr++ = 10;
// determine parent priority
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && (3*mle_class_rfd_entry_count_get(cur->id) > 2*THREAD_MAX_MTD_CHILDREN)) {
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && (3*mle_class_rfd_entry_count_get(cur) > 2*THREAD_MAX_MTD_CHILDREN)) {
*ptr++ = CONNECTIVITY_PP_LOW;
} else if (!(mode & MLE_RX_ON_IDLE) && (3*mle_class_sleepy_entry_count_get(cur->id) > 2*THREAD_MAX_SED_CHILDREN)) {
} else if (!(mode & MLE_RX_ON_IDLE) && (3*mle_class_sleepy_entry_count_get(cur) > 2*THREAD_MAX_SED_CHILDREN)) {
*ptr++ = CONNECTIVITY_PP_LOW;
} else if (3*thread_router_bootstrap_child_count_get(cur) > 2*thread->maxChildCount) {
// 1/3 of the child capacity remaining, PP=low
*ptr++ = CONNECTIVITY_PP_LOW;
} else if (mle_class_free_entry_count_get(cur->id) < THREAD_FREE_MLE_ENTRY_THRESHOLD) {
} else if (mle_class_free_entry_count_get(cur) < THREAD_FREE_MLE_ENTRY_THRESHOLD) {
// If only few entries available in the MLE table, change priority to low
*ptr++ = CONNECTIVITY_PP_LOW;
} else {
@ -1829,7 +1858,7 @@ static uint8_t * thread_commissioner_port_tlv_write(uint16_t port, uint8_t *ptr)
return common_write_16_bit(port, ptr);
}
static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, mle_neigh_table_entry_t *neighbor)
static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failures, uint8_t attribute_index)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(nwk_id);
@ -1839,27 +1868,33 @@ static void thread_tx_failure_handler(int8_t nwk_id, uint8_t accumulated_failure
return;
}
mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_attribute_discover(mac_neighbor_info(cur), attribute_index);
if (!neighbor) {
return;
}
if (accumulated_failures >= THREAD_MAC_TRANSMISSIONS*THREAD_FAILED_CHILD_TRANSMISSIONS) {
mle_class_remove_entry(cur->id, neighbor);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neighbor);
}
}
/* Called when MLE link to neighbour lost, or ETX callback says link is bad */
void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *neighbour)
void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbour)
{
thread_parent_info_t *thread_endnode_parent = thread_info(cur)->thread_endnode_parent;
if (!thread_i_am_router(cur) && thread_endnode_parent && thread_endnode_parent->shortAddress == neighbour->short_adr) {
if (!thread_i_am_router(cur) && thread_endnode_parent && thread_endnode_parent->shortAddress == neighbour->mac16) {
if(cur->nwk_bootstrap_state != ER_CHILD_ID_REQ) {
tr_warn("End device lost parent, reset!\n");
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
}
}
thread_routing_remove_link(cur, neighbour->short_adr);
thread_routing_remove_link(cur, neighbour->mac16);
thread_router_bootstrap_reset_child_info(cur, neighbour);
protocol_6lowpan_release_long_link_address_from_neighcache(cur, neighbour->mac64);
mac_helper_devicetable_remove(cur->mac_api, neighbour->attribute_index);
mac_helper_devicetable_remove(cur->mac_api, neighbour->index);
thread_neighbor_class_entry_remove(&cur->thread_info->neighbor_class, neighbour->index);
}
uint8_t thread_get_router_count_from_route_tlv(mle_tlv_info_t *routeTlv)
@ -1894,7 +1929,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);
thread_extension_address_registration(interface, addr->address, NULL, false, false);
}
}
}
@ -1902,9 +1937,6 @@ static void thread_address_notification_cb(struct protocol_interface_info_entry
void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added)
{
(void) addr_added;
group->mld_timer = 0;
if (thread_attach_ready(interface) != 0) {
return;
@ -1918,11 +1950,13 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface,
interface->thread_info->childUpdateReqTimer = 1;
}
} else {
thread_extension_mcast_subscrition_change(interface, group, addr_added);
if (addr_added) {
thread_address_registration_timer_set(interface, 0, 1);
}
}
}
void thread_old_partition_data_purge(protocol_interface_info_entry_t *cur)
void thread_partition_data_purge(protocol_interface_info_entry_t *cur)
{
/* Partition has been changed. Wipe out data related to old partition */
thread_management_client_pending_coap_request_kill(cur->id);
@ -1935,5 +1969,33 @@ void thread_old_partition_data_purge(protocol_interface_info_entry_t *cur)
}
bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
{
if (thread_info(cur)->thread_leader_data) {
if ((thread_info(cur)->thread_leader_data->partitionId == leaderData->partitionId) &&
(thread_info(cur)->thread_leader_data->weighting == leaderData->weighting)) {
return true;
}
}
return false;
}
void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
{
/* Force network data update later when processing network data TLV */
thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1;
thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1;
thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId;
thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId;
thread_info(cur)->thread_leader_data->weighting = leaderData->weighting;
/* New network data learned, get rid of old partition data */
thread_partition_data_purge(cur);
}
void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index)
{
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index);
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -40,6 +40,8 @@
#include "eventOS_event_timer.h"
#include "MLE/mle_tlv.h"
struct mac_neighbor_table_entry;
#define MAX_MLE_CHALLENGE_LENGTH 32
/*
@ -55,8 +57,8 @@
#define NETWORK_ID_TIMEOUT 120 //seconds
// Values when adverticements are made faster when leader connection is restored
#define NETWORK_ID_SPEEDUP 60 //seconds
#define NETWORK_ID_SPEEDUP_MAX 100 //seconds
#define NETWORK_ID_SPEEDUP 55 //seconds
#define NETWORK_ID_SPEEDUP_MAX 80 //seconds
#define DHCPV6_ENTERPRISE_THREAD 0x0000AFAA
#define DHCPV6_OPTION_VENDOR_SPESIFIC_INFO_LEN 0x0011
@ -92,6 +94,22 @@ typedef enum {
THREAD_COMMISSIONER_REGISTERED
} thread_commissioner_register_status_e;
typedef struct thread_neigh_table_entry_s {
uint8_t mlEid[8];
uint32_t last_contact_time; /*!< monotonic time - hard to define "contact"; used for Thread Leasequery replies */
uint16_t link_margin;
bool secured_data_request:1;
bool request_full_data_set:1;
} thread_neigh_table_entry_t ;
/**
* Neighbor info data base
*/
typedef struct thread_neighbor_class_s {
thread_neigh_table_entry_t *neigh_info_list; /*!< Allocated Neighbour info array*/
uint8_t list_size; /*!< List size*/
} thread_neighbor_class_t;
typedef struct thread_mcast_child {
uint8_t mac64[8];
ns_list_link_t link;
@ -261,6 +279,7 @@ typedef struct thread_previous_partition_info_s {
typedef struct thread_info_s {
thread_routing_info_t routing;
thread_neighbor_class_t neighbor_class;
thread_master_secret_material_t masterSecretMaterial;
thread_network_data_cache_entry_t networkDataStorage;
thread_network_local_data_cache_entry_t localServerDataBase;
@ -363,7 +382,7 @@ uint16_t thread_network_data_generate_stable_set(protocol_interface_info_entry_t
void thread_set_active_router(protocol_interface_info_entry_t *cur, if_address_entry_t *address_entry, uint8_t *routerId);
uint8_t thread_get_router_count_from_route_tlv(mle_tlv_info_t *routeTlv);
void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *neighbour);
void thread_reset_neighbour_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *neighbour);
void thread_child_id_request_entry_clean(protocol_interface_info_entry_t *cur);
thread_pending_child_id_req_t *thread_child_id_request_entry_get(protocol_interface_info_entry_t *cur, uint8_t *euid64);
@ -413,15 +432,19 @@ uint8_t *thread_pending_operational_dataset_write(protocol_interface_info_entry_
bool thread_pending_operational_dataset_process(protocol_interface_info_entry_t *cur, uint64_t mle_pending_timestamp, uint8_t *ptr, uint16_t len);
/*Write optional thread leader data TLV if leader data is known*/
uint8_t thread_pending_timestamp_tlv_size(protocol_interface_info_entry_t *cur);
void thread_calculate_key_guard_timer(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, bool is_init);
void thread_key_guard_timer_calculate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, bool is_init);
void thread_key_guard_timer_reset(protocol_interface_info_entry_t *cur);
void thread_set_link_local_address(protocol_interface_info_entry_t *cur);
void thread_mcast_group_change(struct protocol_interface_info_entry *interface, struct if_group_entry *group, bool group_added);
void thread_old_partition_data_purge(protocol_interface_info_entry_t *cur);
void thread_partition_data_purge(protocol_interface_info_entry_t *cur);
bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
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);
#else // HAVE_THREAD
NS_DUMMY_DEFINITIONS_OK
#define thread_stable_context_check(cur, buf) (false)
#define thread_info(cur) ((thread_info_t *) NULL)
#define thread_am_router(cur) (false)
#define thread_am_host(cur) (false)
@ -438,6 +461,7 @@ NS_DUMMY_DEFINITIONS_OK
#define thread_link_reject_send(interface, ll64) 0
#define thread_addr_is_mesh_local_16(addr, cur) false
#define thread_mcast_group_change(interface, group, group_added) ((void)0)
#define thread_neighbor_communication_update(cur, neighbor_attribute_index) ((void)0)
#endif // HAVE_THREAD
#endif /* LOWPAN_THREAD_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -39,6 +39,7 @@
#include "thread_joiner_application.h"
#include "thread_leader_service.h"
#include "thread_router_bootstrap.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "MLE/mle.h"
#include "6LoWPAN/Thread/thread_router_bootstrap.h"
#include "thread_config.h"
@ -47,6 +48,7 @@
#include "thread_diagcop_lib.h"
#include "common_functions.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "mac_api.h"
@ -93,31 +95,31 @@ static uint8_t *thread_diagnostic_child_table_tlv_build(uint8_t *data_ptr, proto
uint8_t child_count = 0;
uint8_t calculated_timeout;
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
if (!mle_table) {
return data_ptr;
}
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
child_count = thread_router_bootstrap_child_count_get(cur);
*data_ptr++ = DIAGCOP_TLV_CHILD_TABLE; // Type
*data_ptr++ = (3 * child_count); // Length
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if (cur_entry->threadNeighbor && thread_router_addr_from_addr(cur_entry->short_adr) == mac_helper_mac16_address_get(cur)){
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (thread_router_addr_from_addr(cur_entry->mac16) == mac_helper_mac16_address_get(cur)){
/* |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3| */
/* |Timeout |Rsv| Child ID | Mode | */
calculated_timeout = thread_log2_aprx((cur_entry->timeout_rx-1)*MLE_TIMER_TICKS_SECONDS) + 4;
tr_debug("Write child table TLV entry: %d - %d - %d", calculated_timeout, cur_entry->short_adr, cur_entry->mode);
calculated_timeout = thread_log2_aprx(cur_entry->link_lifetime - 1) + 4;
uint8_t mode = 0;
mode |= mle_mode_write_from_mac_entry(cur_entry);
mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, cur_entry->index);
tr_debug("Write child table TLV entry: %d - %d - %d", calculated_timeout, cur_entry->mac16, mode);
*data_ptr = 0x00; //reserved bytes to zero
*data_ptr = calculated_timeout << 3;
if(cur_entry->short_adr & 0x0100){
if(cur_entry->mac16 & 0x0100){
*data_ptr = *data_ptr | 0x01;
}
data_ptr++;
*data_ptr++ = (uint8_t)(cur_entry->short_adr & 0x00ff);
*data_ptr++ = cur_entry->mode;
*data_ptr++ = (uint8_t)(cur_entry->mac16 & 0x00ff);
*data_ptr++ = mode;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -818,7 +818,7 @@ static void thread_discovery_request_msg_handler(thread_discovery_class_t * disc
tr_debug("Thread discovery request message RX");
// Check if we have room for new neighbor
if (mle_class_free_entry_count_get(discovery_class->interface_id) < 1) {
if (mle_class_free_entry_count_get(discovery_class->interface) < 1) {
tr_debug("MLE table full, skip request");
return;
}
@ -1281,10 +1281,10 @@ static void thread_discovery_normal_receive_cb(int8_t interface_id, mle_message_
/**
* Start Thread network discovery
*/
int thread_discovery_network_scan(int8_t interface_id, thread_discover_reques_t *scan_request, thread_discovery_ready_cb *ready_cb)
int thread_discovery_network_scan(struct protocol_interface_info_entry *cur_interface, thread_discover_reques_t *scan_request, thread_discovery_ready_cb *ready_cb)
{
thread_discovery_class_t * discovery_class = thread_discovery_class_get(interface_id);
thread_discovery_class_t * discovery_class = thread_discovery_class_get(cur_interface->id);
if (!discovery_class || !ready_cb || !scan_request) {
return -1;
}
@ -1304,12 +1304,12 @@ int thread_discovery_network_scan(int8_t interface_id, thread_discover_reques_t
return -3;
}
if (mle_service_interface_register(interface_id, thread_discovery_normal_receive_cb, discovery_class->discovery_request->temporary_mac64,8) != 0) {
if (mle_service_interface_register(cur_interface->id, cur_interface, thread_discovery_normal_receive_cb, discovery_class->discovery_request->temporary_mac64,8) != 0) {
thread_discovery_request_free(discovery_class);
return -1;
}
if (mle_service_interface_receiver_bypass_handler_update(interface_id, thread_discovery_message_receiver_cb) != 0) {
if (mle_service_interface_receiver_bypass_handler_update(cur_interface->id, thread_discovery_message_receiver_cb) != 0) {
thread_discovery_request_free(discovery_class);
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -122,7 +122,7 @@ int thread_discovery_responser_enable(int8_t interface_id, bool enable_service);
/**
* Start Thread network discovery
*/
int thread_discovery_network_scan(int8_t interface_id, thread_discover_reques_t *scan_request, thread_discovery_ready_cb *ready_cb);
int thread_discovery_network_scan(struct protocol_interface_info_entry *cur_interface, thread_discover_reques_t *scan_request, thread_discovery_ready_cb *ready_cb);
/**
* Start device orphan scan

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -40,27 +40,66 @@ extern "C" {
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);
int thread_extension_network_prefix_get(int8_t interface_id, uint8_t *options_ptr, uint8_t *prefix_ptr, uint8_t *prefix_len);
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_address_generate(protocol_interface_info_entry_t *cur);
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);
void thread_extension_route_set(protocol_interface_info_entry_t *cur);
void thread_extension_activate(protocol_interface_info_entry_t *cur);
bool thread_extension_enabled(protocol_interface_info_entry_t *cur);
bool thread_extension_context_can_delete(int8_t id, uint8_t servicesPrefix[16], uint8_t context_prefix_length);
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);
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_discover_response_len(cur) 0
#define thread_extension_discover_response_write(cur, ptr) (ptr)
#endif //HAVE_THREAD_ROUTER
#else
#define thread_extension_allocate(cur)
#define thread_extension_free(cur)
#define thread_extension_init(interface_id,coap_service_id)
#define thread_extension_network_prefix_get(interface_id,options_ptr,prefix_ptr,prefix_len) (-1)
#define thread_extension_network_data_process(cur)
#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)
#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected)
#define thread_extension_address_generate(cur)
#define thread_extension_aloc_generate(cur)
#define thread_extension_aloc_map(cur, addr16) false
#define thread_extension_mcast_subscrition_change(interface, group, added)
#define thread_extension_mcast_subscrition_change(interface)
#define thread_extension_route_set(cur)
#define thread_extension_activate(cur)
#define thread_extension_enabled(cur) (false)
#define thread_extension_version_check(version) (false)
#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len)
#define thread_extension_discover_response_tlv_write(data, version, extension_bit) (data)
#define thread_extension_joiner_router_init(interface_id)
#define thread_extension_service_init(cur) 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)
#define thread_extension_context_can_delete(id, servicesPrefix, context_prefix_length) false
#endif
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -38,6 +38,14 @@
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);
@ -47,6 +55,7 @@ void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds);
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);
#else
@ -58,6 +67,7 @@ void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur);
#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_prefix_set(interface_id, prefix) 0
#endif
#ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -63,6 +63,7 @@
#include "6LoWPAN/Thread/thread_management_client.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h"
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "thread_management_if.h"
#include "Common_Protocols/ipv6.h"
#include "MPL/mpl.h"
@ -73,6 +74,7 @@
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "Core/include/address.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "tebs"
@ -122,7 +124,8 @@ static void thread_merge_prepare(protocol_interface_info_entry_t *cur)
thread_clean_old_16_bit_address_based_addresses(cur);
mpl_clear_realm_scope_seeds(cur);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
thread_old_partition_data_purge(cur);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
thread_partition_data_purge(cur);
thread_network_data_clean(cur);
cur->nwk_mode = ARM_NWK_GP_IP_MODE;
}
@ -145,7 +148,7 @@ static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgI
uint8_t ll64[16];
thread_scanned_parent_t *parent = cur->thread_info->thread_attach_scanned_parent;
link_configuration_s *linkConfiguration;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
linkConfiguration = thread_joiner_application_get_config(interface_id);
if (!linkConfiguration) {
@ -156,22 +159,25 @@ static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgI
memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8);
memcpy(&ll64[8], parent->mac64 , 8);
ll64[8] ^= 2;
entry_temp = mle_class_get_entry_by_ll64(interface_id, parent->linkMarginToParent,ll64, true, &new_entry_created);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, true, &new_entry_created);
if (entry_temp == NULL) {
return false;
}
entry_temp->threadNeighbor = true;
entry_temp->short_adr = parent->shortAddress;
entry_temp->priorityFlag = true;
entry_temp->holdTime = 90;
entry_temp->mle_frame_counter = parent->mleFrameCounter;
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, parent->linkMarginToParent, new_entry_created);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
entry_temp->mac16 = parent->shortAddress;
entry_temp->link_role = PRIORITY_PARENT_NEIGHBOUR;
mle_service_frame_counter_entry_add(interface_id, entry_temp->index, parent->mleFrameCounter);
thread_management_key_sets_calc(cur, linkConfiguration, cur->thread_info->thread_attach_scanned_parent->keySequence);
thread_calculate_key_guard_timer(cur, linkConfiguration, true);
thread_key_guard_timer_calculate(cur, linkConfiguration, true);
mac_helper_devicetable_set(entry_temp, cur, parent->linLayerFrameCounter, mac_helper_default_key_index_get(cur), new_entry_created);
mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,parent->linLayerFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur,entry_temp->index, mac_helper_default_key_index_get(cur), new_entry_created);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 50);
@ -284,6 +290,8 @@ void thread_network_attach_start(protocol_interface_info_entry_t *cur)
tr_debug("MLE Parent request");
cur->nwk_bootstrap_state = ER_MLE_SCAN;
cur->bootsrap_state_machine_cnt = 0;
/* advance trickle timer by 6 (in 100ms ticks) seconds if needed */
thread_routing_trickle_advance(&cur->thread_info->routing, 6*10);
} else {
cur->bootsrap_state_machine_cnt = 5;
}
@ -297,7 +305,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
uint16_t address16;
uint32_t llFrameCounter;
thread_leader_data_t leaderData;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
bool new_entry_created;
tr_debug("Validate Link Synch Response");
@ -323,31 +331,36 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource));
// if learning key sequence from link sync actual guard timer value is not known
thread_key_guard_timer_reset(cur);
} else {
tr_debug("Key ID Mode 2 not used; dropped.");
return -3;
}
//Update parent link information
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, src_address, true, &new_entry_created);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), src_address, true, &new_entry_created);
if (!entry_temp) {
tr_debug("Neighbor allocate fail");
return -2;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, new_entry_created);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
/*
*/
entry_temp->threadNeighbor = true;
entry_temp->short_adr = srcAddress;
entry_temp->handshakeReady = 1;
entry_temp->holdTime = 90;
entry_temp->priorityFlag = true; // Make this our parent
common_write_16_bit(entry_temp->short_adr, shortAddress);
entry_temp->mac16 = srcAddress;
entry_temp->connected_device = 1;
entry_temp->link_role = PRIORITY_PARENT_NEIGHBOUR; // Make this our parent
common_write_16_bit(entry_temp->mac16, shortAddress);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, shortAddress);
mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout);
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, securityHeader->KeyIndex, new_entry_created);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, thread_info(cur)->host_link_timeout);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,llFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, securityHeader->KeyIndex, new_entry_created);
thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
thread_bootstrap_update_ml16_address(cur, address16);
@ -377,12 +390,10 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
{
(void) interface_id;
tr_debug("Thread MLE message child_synch handler");
//State machine What packet shuold accept in this case
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
/* Check that message is from link-local scope */
if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
@ -466,10 +477,8 @@ static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *
*/
void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
(void) interface_id;
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
/* Check that message is from link-local scope */
if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
@ -538,8 +547,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
if (thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH || thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH_RETRY) {
tr_debug("Reattach");
if (thread_info(cur)->thread_leader_data) {
if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) ||
(thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) {
if (!thread_partition_match(cur, &leaderData)) {
//accept only same ID at reattach phase
return;
}
@ -557,8 +565,7 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED ||
thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
if (thread_info(cur)->thread_leader_data) {
if ((thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) &&
(thread_info(cur)->thread_leader_data->weighting == leaderData.weighting)) {
if (thread_partition_match(cur, &leaderData)) {
//accept only different ID at anyattach phase
tr_debug("Drop old partition");
return;
@ -736,12 +743,9 @@ void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *m
static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
{
thread_leader_data_t leaderData;
mle_neigh_table_entry_t *entry_temp;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
mac_neighbor_table_entry_t *entry_temp;
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
link_configuration_s *link_configuration;
if (!cur) {
return;
}
link_configuration = thread_joiner_application_get_config(cur->id);
if (!link_configuration) {
return;
@ -790,17 +794,19 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
thread_merge_prepare(cur);
// Create entry for new parent
entry_temp = mle_class_get_entry_by_ll64(cur->id, thread_compute_link_margin(mle_msg->dbm), mle_msg->packet_src_address, true, &new_entry_created);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, &new_entry_created);
if (entry_temp == NULL) {
// todo: what to do here?
return;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, thread_compute_link_margin(mle_msg->dbm), new_entry_created);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
//Parse mandatory TLV's
if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
return;
}
if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &entry_temp->short_adr)) {
if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &entry_temp->mac16)) {
return;
}
@ -836,25 +842,24 @@ static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message
return;
}
common_write_16_bit(entry_temp->short_adr, shortAddress);
common_write_16_bit(entry_temp->mac16, shortAddress);
//Update possible reed address by real router address
scan_result->shortAddress = entry_temp->short_adr;
scan_result->shortAddress = entry_temp->mac16;
entry_temp->holdTime = 90;
entry_temp->handshakeReady = 1;
entry_temp->priorityFlag = true;
entry_temp->threadNeighbor = true;
entry_temp->connected_device = 1;
entry_temp->link_role = PRIORITY_PARENT_NEIGHBOUR;
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, shortAddress);
mle_entry_timeout_update(entry_temp, thread_info(cur)->host_link_timeout);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, thread_info(cur)->host_link_timeout);
if (scan_result->security_key_index != security_headers->KeyIndex) {
// KeyIndex has been changed between parent_response and child_id_response, reset link layer frame counter
scan_result->linLayerFrameCounter = 0;
scan_result->security_key_index = security_headers->KeyIndex;
}
mac_helper_devicetable_set(entry_temp, cur, scan_result->linLayerFrameCounter, security_headers->KeyIndex, new_entry_created);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,scan_result->linLayerFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, security_headers->KeyIndex, new_entry_created);
thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
@ -948,23 +953,26 @@ static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur
void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
{
if (cur->thread_info->thread_endnode_parent) {
mle_neigh_table_entry_t *entry_temp;
bool new_entry_created;
// Add the parent to the MLE neighbor table
entry_temp = mle_class_get_entry_by_mac64(cur->id, 64, cur->thread_info->thread_endnode_parent->mac64, true, &new_entry_created);
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(cur), cur->thread_info->thread_endnode_parent->mac64, true, &new_entry_created);
if (mac_entry) {
//Add link margin 64
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, mac_entry->index,64, new_entry_created);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, mac_entry->index);
if (entry_temp) {
entry_temp->short_adr = cur->thread_info->thread_endnode_parent->shortAddress;
entry_temp->handshakeReady = 1;
entry_temp->threadNeighbor = true;
mac_entry->mac16 = cur->thread_info->thread_endnode_parent->shortAddress;
mac_entry->connected_device = 1;
// In case we don't get response to sync; use temporary timeout here,
// Child ID Response handler will set correct value later
mle_entry_timeout_update(entry_temp, 20);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_entry, mac_entry->link_lifetime);
// Add the parent to the MAC table (for e.g. secured/fragmented Child Update Response)
mac_helper_devicetable_set(entry_temp, cur, 0, cur->mac_parameters->mac_default_key_index, new_entry_created);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, mac_entry->mac64, mac_entry->mac16,0, false);
mac_helper_devicetable_set(&device_desc, cur, mac_entry->index, cur->mac_parameters->mac_default_key_index, new_entry_created);
}
}
@ -978,10 +986,9 @@ void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
{
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
thread_scanned_parent_t *scanned_parent;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
uint8_t ll64[16];
(void)msgId;
@ -1017,15 +1024,17 @@ static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, boo
tr_debug("Back to old partition");
/* If scanned parent is from other partition, delete from MLE table */
if (scanned_parent->leader_data.partitionId != thread_info(cur)->thread_leader_data->partitionId) {
memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8);
memcpy(&ll64[8], scanned_parent->mac64 , 8);
ll64[8] ^= 2;
entry_temp = mle_class_get_entry_by_ll64(cur->id, scanned_parent->linkMarginToParent, ll64, false, NULL);
if (entry_temp && !thread_check_is_this_my_parent(cur, entry_temp)) {
// remove scanned_parent entry only if it is not my parent
mle_class_remove_entry(cur->id, entry_temp);
if ((scanned_parent->leader_data.partitionId != thread_info(cur)->thread_leader_data->partitionId) ||
(scanned_parent->leader_data.weighting != thread_info(cur)->thread_leader_data->weighting)) {
entry_temp = mac_neighbor_table_address_discover(mac_neighbor_info(cur), scanned_parent->mac64, ADDR_802_15_4_LONG);
if (entry_temp) {
bool my_parent = thread_check_is_this_my_parent(cur, entry_temp);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
if (my_parent) {
tr_debug("No parent resp - any-attach");
thread_bootstrap_connection_error(interface_id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL);
goto exit;
}
}
}
@ -1159,22 +1168,22 @@ static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId,
}
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64)
bool thread_host_bootstrap_child_update(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
mle_message_timeout_params_t timeout;
uint8_t mode;
uint32_t keySequence;
if (!cur->thread_info->thread_endnode_parent) {
return -1;
tr_debug("Not end device parent info for NUD");
return false;
}
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
//Set Pending if earlier process is already started
cur->thread_info->thread_endnode_parent->childUpdatePending = true;
return -1;
return false;
}
//Trig event
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
@ -1189,7 +1198,7 @@ int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *ma
uint16_t bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false, MLE_COMMAND_CHILD_UPDATE_REQUEST);
if (bufId == 0) {
return -1;
return false;
}
thread_management_get_current_keysequence(cur->id, &keySequence);
@ -1228,7 +1237,7 @@ int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *ma
mle_service_set_msg_timeout_parameters(bufId, &timeout);
mle_service_send_message(bufId);
return 0;
return true;
}
int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -42,7 +42,7 @@ struct protocol_interface_info_entry;
struct mle_security_header;
void thread_network_attach_start(struct protocol_interface_info_entry *cur);
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64);
bool thread_host_bootstrap_child_update(struct protocol_interface_info_entry *cur, const uint8_t *mac64);
int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge);
void thread_child_set_default_route(struct protocol_interface_info_entry *cur);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -778,8 +778,8 @@ static bool thread_joiner_application_validate_settings(thread_joiner_t *this)
new_value_generated = 1;
tr_info("Generating Random ML-EID");
}
if (this->configuration_ptr->key_rotation < 3600) {
this->configuration_ptr->key_rotation = 3600;
if (this->configuration_ptr->key_rotation < 1) {
this->configuration_ptr->key_rotation = 1;
}
return new_value_generated;
}
@ -967,17 +967,12 @@ static int thread_joiner_application_nvm_link_config_read(thread_joiner_t *this)
this->configuration_valid = true;
link_configuration_trace(this->configuration_ptr);
//Add Security to MLE service
uint8_t key_material[32];
uint8_t key_index;
//Define KEY's
thread_key_get(this->configuration_ptr->master_key, key_material, this->configuration_ptr->key_sequence);
key_index = THREAD_KEY_INDEX(this->configuration_ptr->key_sequence);
//Set Keys
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id);
mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
mle_service_security_set_security_key(this->interface_id, key_material, key_index, true);
//Add Security to MLE service
thread_security_prev_key_generate(cur,this->configuration_ptr->master_key,this->configuration_ptr->key_sequence);
thread_security_key_generate(cur,this->configuration_ptr->master_key,this->configuration_ptr->key_sequence);
thread_security_next_key_generate(cur,this->configuration_ptr->master_key,this->configuration_ptr->key_sequence);
// update counters
mle_service_security_set_frame_counter(this->interface_id, fast_data.mle_frame_counter);
mac_helper_link_frame_counter_set(this->interface_id, fast_data.mac_frame_counter);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -414,7 +414,7 @@ static int thread_leader_service_active_set_cb(int8_t service_id, uint8_t source
}
}
if (3 <= thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_SECURITY_POLICY, &ptr)) {
if (common_read_16_bit(ptr) < 3600) {
if (common_read_16_bit(ptr) < 1) {
tr_warn("invalid security policy");
ret = -1;
goto send_response;
@ -1090,7 +1090,7 @@ static int thread_leader_service_petition_cb(int8_t service_id, uint8_t source_a
ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff);
}
tr_debug("Petition req recv id %s, RESP session id: %d ret %d", commissioner_id_ptr, session_id, ret);
tr_debug("Petition req recv id %s, RESP session id: %d ret %d", commissioner_id_ptr ? commissioner_id_ptr : "(none)", session_id, ret);
send_error_response:
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, payload, ptr - payload);
@ -1346,7 +1346,7 @@ static void thread_leader_service_interface_setup_activate(protocol_interface_in
thread_leader_service_private_routemask_init(private);
//SET Router ID
thread_leader_allocate_router_id_by_allocated_id(private, routerId, cur->mac);
thread_old_partition_data_purge(cur);
thread_partition_data_purge(cur);
// remove any existing rloc mapping in nvm
thread_nvm_store_mleid_rloc_map_remove();
cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
@ -1526,7 +1526,7 @@ void thread_leader_service_timer(protocol_interface_info_entry_t *cur, uint32_t
cur->thread_info->leader_private_data->leader_id_seq_timer = ID_SEQUENCE_PERIOD;
thread_leader_service_update_id_set(cur);
thread_network_data_context_re_use_timer_update(&cur->thread_info->networkDataStorage, 10, &cur->lowpan_contexts);
thread_network_data_context_re_use_timer_update(cur->id, &cur->thread_info->networkDataStorage, 10, &cur->lowpan_contexts);
// Send update to network data if needed
thread_leader_service_network_data_changed(cur, false, false);
}
@ -1621,7 +1621,6 @@ void thread_leader_service_thread_partitition_generate(int8_t interface_id, bool
//memset(cur->thread_info->lastValidRouteMask, 0, (N_THREAD_ROUTERS+7)/8);
//SET SHort Address & PAN-ID
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
cur->interface_mode = INTERFACE_UP;
cur->nwk_mode = ARM_NWK_GP_IP_MODE;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -146,6 +146,8 @@ void thread_management_client_init(int8_t interface_id)
if (this) {
this->network_data_set_cb_ptr = NULL;
this->router_id_release_cb_ptr = NULL;
this->neighbor_discovery_cb_ptr = NULL;
this->router_id_cb_ptr = NULL;
this->interface_id = interface_id;
this->coap_asd_msg_id = 0;
@ -333,6 +335,15 @@ static int thread_management_client_neighbor_discovery_data_cb(int8_t service_id
return 0;
}
int thread_management_client_get_interface_id_by_service_id(int8_t service_id)
{
thread_management_t *this = thread_management_find_by_service(service_id);
if (!this) {
return -1;
}
return this->interface_id;
}
int thread_management_client_neighbor_discovery_data_request(int8_t interface_id, const uint8_t destination[16], const uint8_t *options, uint8_t options_len, thread_management_client_network_data_set_cb *set_cb)
{
thread_management_t *this = thread_management_find(interface_id);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -148,6 +148,15 @@ int thread_management_client_network_data_unregister(int8_t interface_id, uint16
*/
int thread_management_client_neighbor_discovery_data_request(int8_t interface_id, const uint8_t destination[16], const uint8_t *options, uint8_t options_len, thread_management_client_network_data_set_cb *set_cb);
/** Get interface_id of based on coap service_id
*
*
* /param service_id coap service id.
*
*return interface_id of thread instance if successful and -1 for failure
*/
int thread_management_client_get_interface_id_by_service_id(int8_t service_id);
/** send active configuration dataset get for parent
*
* /param interface_id interface id of this thread instance.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -62,6 +62,7 @@
#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/Bootstraps/protocol_6lowpan.h"
#include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up
#include "MLE/mle.h"
@ -77,7 +78,9 @@
#include "Service_Libs/blacklist/blacklist.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_pairwise_key.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "mac_common_defines.h"
#include "mlme.h"
#include "mac_api.h"
@ -307,68 +310,6 @@ void thread_key_get(uint8_t *key, uint8_t *key_material_buf, uint32_t key_seque
SHALIB_finish_HMAC(key_material_buf, 8);
}
/**
* Increment Thread key sequence counter
*
* \param interface_id Network Interface
*
* return 0, ADD OK
* return <0 Add Not OK
*/
uint8_t *thread_management_key_request(int8_t interface_id, uint8_t keyId)
{
protocol_interface_info_entry_t *cur;
uint8_t *keyPtr = NULL;
link_configuration_s *linkConfiguration;
linkConfiguration = thread_joiner_application_get_config(interface_id);
if (!linkConfiguration) {
return NULL;
}
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur && cur->thread_info) {
if (cur->thread_info->masterSecretMaterial.valid_Info) {
if (cur->thread_info->masterSecretMaterial.historyKeyValid && (cur->thread_info->masterSecretMaterial.historyKeyId == keyId)) {
keyPtr = cur->thread_info->masterSecretMaterial.historyKey;
} else {
uint32_t thrSequenceCounter;
uint8_t compId = 0xff, keyIdDiff;
thrSequenceCounter = linkConfiguration->key_sequence + 1;
//Calculate Current Next key ID
compId = THREAD_KEY_INDEX(thrSequenceCounter);
if (keyId > compId) {
keyIdDiff = (keyId - compId);
} else {
keyIdDiff = (128 - (compId - keyId));
}
if (keyIdDiff > 64) {
//Calc Temp Key
thrSequenceCounter -= (128 - keyIdDiff);
tr_debug("Gen temporary key id %"PRIu8" seq %"PRIu32, keyId, thrSequenceCounter);
thread_key_get(linkConfiguration->master_key, cur->thread_info->masterSecretMaterial.historyKey, thrSequenceCounter);
cur->thread_info->masterSecretMaterial.historyKeyId = keyId;
cur->thread_info->masterSecretMaterial.historyKeyValid = true;
keyPtr = cur->thread_info->masterSecretMaterial.historyKey;
} else {
tr_debug("Gen new key id %"PRIu8" %"PRIu8" diff", keyId, keyIdDiff);
thrSequenceCounter += keyIdDiff;
//Generate
tr_debug("Missed n key Update...generated missed key %"PRIu8" update by seq %"PRIu32, keyIdDiff, thrSequenceCounter);
thread_management_key_sets_calc(cur, linkConfiguration, thrSequenceCounter);
//Get Default key
keyPtr = mle_service_security_default_key_get(interface_id);
}
thread_nvm_store_seq_counter_write(linkConfiguration->key_sequence);
}
}
}
return keyPtr;
}
/**
* Thread key sequence & key synch
*
@ -381,22 +322,32 @@ void thread_management_key_synch_req(int8_t interface_id, uint32_t keySequnce)
if (!linkConfiguration) {
return;
}
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur && cur->thread_info) {
if (cur->thread_info->masterSecretMaterial.valid_Info) {
if (keySequnce != linkConfiguration->key_sequence) {
if ((cur->thread_info->masterSecretMaterial.keySwitchGuardTimer == 0 && keySequnce > linkConfiguration->key_sequence)) {
if (!cur || !cur->thread_info) {
return;
}
if (!cur->thread_info->masterSecretMaterial.valid_Info) {
return;
}
//tr_debug("Sync key material by %"PRIu32, keySequnce);
if (keySequnce <= linkConfiguration->key_sequence) {
// Smaller or equal request ignored
//tr_debug("Sync key material no change");
return;
}
if ((cur->thread_info->masterSecretMaterial.keySwitchGuardTimer > 0)) {
// Guard time prevent the change
//tr_debug("Sync key material guard blocked");
return;
}
// Calculate new keys
tr_debug("Sync key material by %"PRIu32, keySequnce);
thread_management_key_sets_calc(cur, linkConfiguration, keySequnce);
thread_calculate_key_guard_timer(cur, linkConfiguration, false);
}
}
}
}
thread_key_guard_timer_calculate(cur, linkConfiguration, false);
}
void thread_history_key_material_push(thread_info_t *thread_info, uint8_t *mleKeyPtr, uint8_t keyId)
static void thread_history_key_material_push(thread_info_t *thread_info, uint8_t *mleKeyPtr, uint8_t keyId)
{
thread_info->masterSecretMaterial.historyKeyValid = true;
thread_info->masterSecretMaterial.historyKeyId = keyId;
@ -424,7 +375,7 @@ void thread_security_update_from_mac(protocol_interface_info_entry_t *cur)
linkConfiguration->key_sequence++;
mac_helper_link_frame_counter_set(cur->id, 0);
thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
thread_calculate_key_guard_timer(cur, linkConfiguration, false);
thread_key_guard_timer_calculate(cur, linkConfiguration, false);
}
void thread_security_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
@ -437,11 +388,33 @@ void thread_security_key_generate(protocol_interface_info_entry_t *cur, uint8_t
thread_key_get(masterKey, key_material, thrKeySequenceCounter);
/* Update keys as primary keys */
key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
tr_debug("Set key Id: %u", key_index);
tr_debug("Set current key Id: %u", key_index);
mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
mle_service_security_set_security_key(cur->id, key_material, key_index, true);
}
void thread_security_prev_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
{
uint8_t key_material[32];
uint8_t key_index;
uint32_t thrKeySequenceCounter;
if (keySequence == 0) {
// in initial value there is no prev available
return;
}
thrKeySequenceCounter = keySequence - 1;
/* Produced keys from Thread security material: MAC key | MLE key */
thread_key_get(masterKey, key_material, thrKeySequenceCounter);
/* Update keys as primary keys */
key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
tr_debug("Set previous key Id: %u", key_index);
mac_helper_security_prev_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
mle_service_security_set_security_key(cur->id, key_material, key_index, false);
//copy master secret material to history
thread_history_key_material_push(cur->thread_info, key_material, key_index);
}
void thread_security_next_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
{
uint8_t key_material[32];
@ -471,31 +444,17 @@ int thread_management_key_sets_calc(protocol_interface_info_entry_t *cur, link_c
ret_val = 0;
} else {
/* Generate new key set */
uint8_t key_material[32];
uint8_t key_index;
thread_nvm_fast_data_t fast_data;
//SET History key, Current Key & Next Key
//Generate History Key
//Clean All Keys
mac_helper_security_key_clean(cur);
thrKeySequenceCounter--;
/* Update keys as non-primary keys */
thread_key_get(linkConfiguration->master_key, key_material, thrKeySequenceCounter);
key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
//copy master secret material to history
memcpy(cur->thread_info->masterSecretMaterial.historyKey, key_material, 32);
cur->thread_info->masterSecretMaterial.historyKeyId = key_index;
cur->thread_info->masterSecretMaterial.historyKeyValid = true;
mac_helper_security_prev_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
//Set New Active Key
thrKeySequenceCounter++;
// Update key sequence
linkConfiguration->key_sequence = thrKeySequenceCounter;
fast_data.seq_counter = thrKeySequenceCounter;
fast_data.mac_frame_counter = 0;
fast_data.mle_frame_counter = mle_service_security_get_frame_counter(cur->interface_mode);
thread_nvm_store_fast_data_write(&fast_data);
// Zero all frame counters. MLE does it automatically
mac_helper_link_frame_counter_set(cur->id, 0);
// Store all frame counters as zero and update the sequence counter
thread_nvm_store_fast_data_write_all(0, 0, thrKeySequenceCounter);
thread_security_prev_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
thread_security_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
thread_security_next_key_generate(cur,linkConfiguration->master_key,linkConfiguration->key_sequence);
ret_val = 0;
@ -790,12 +749,23 @@ int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr)
}
#ifdef HAVE_THREAD
static mac_neighbor_table_entry_t *neighbor_data_poll_referesh(protocol_interface_info_entry_t *cur, const uint8_t *address, addrtype_t type)
{
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address, type);
if (!entry || !entry->connected_device) {
return NULL;
}
entry->lifetime = entry->link_lifetime;
return entry;
}
void thread_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t* status)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(if_id);
if (!cur) {
return;
}
mac_neighbor_table_entry_t *entry;
switch (status->status) {
@ -808,7 +778,10 @@ void thread_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t* st
break;
case MLME_DATA_POLL_NOTIFICATION:
mle_refresh_entry_timeout(if_id, status->SrcAddr, (addrtype_t)status->SrcAddrMode, false);
entry = neighbor_data_poll_referesh(cur, status->SrcAddr, (addrtype_t)status->SrcAddrMode);
if (entry) {
thread_neighbor_communication_update(cur, entry->index);
}
break;
default:
break;
@ -908,7 +881,7 @@ int thread_management_node_init(
scan_params->scan_duration = 5;
cur->thread_info->masterSecretMaterial.valid_Info = false;
thread_calculate_key_guard_timer(cur, static_configuration, true);
thread_key_guard_timer_calculate(cur, static_configuration, true);
cur->thread_info->maxChildCount = THREAD_MAX_CHILD_COUNT;
cur->thread_info->rfc6775 = false;
@ -1439,11 +1412,22 @@ int thread_management_partition_weighting_set(int8_t interface_id, uint8_t parti
return 0;
}
bool trig_network_scan = false;
if (cur->thread_info->thread_leader_data) {
if (cur->thread_info->thread_leader_data->weighting < partition_weighting) {
trig_network_scan = true;
}
}
cur->thread_info->partition_weighting = partition_weighting;
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
if (trig_network_scan && thread_extension_enabled(cur)) {
thread_nvm_store_link_info_clear();
// bootstrap active and weighting has changed
thread_bootstrap_reset_restart(interface_id);
}
}
return 0;
#else

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -77,15 +77,13 @@ int thread_management_increment_key_sequence_counter(int8_t interface_id);
int thread_management_key_sets_calc(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, uint32_t thrKeySequenceCounter);
uint8_t *thread_management_key_request(int8_t interface_id, uint8_t keyId);
void thread_management_key_synch_req(int8_t interface_id, uint32_t keySequnce);
uint8_t *thread_management_key_request_with_sequence(int8_t interface_id, uint8_t keyId, uint32_t keySequnce);
void thread_security_update_from_mac(struct protocol_interface_info_entry *cur);
void thread_history_key_material_push(struct thread_info_s *thread_info, uint8_t *mleKeyPtr, uint8_t keyId);
void thread_security_key_generate(struct protocol_interface_info_entry *cur, uint8_t *masterKey, uint32_t keySequence);
void thread_security_prev_key_generate(struct protocol_interface_info_entry *cur, uint8_t *masterKey, uint32_t keySequence);
void thread_security_next_key_generate(struct protocol_interface_info_entry *cur, uint8_t *masterKey, uint32_t keySequence);
void thread_key_get(uint8_t *key, uint8_t *key_material_buf, uint32_t key_sequence_counter);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -1159,7 +1159,6 @@ int thread_management_server_init(int8_t interface_id)
}
#endif
thread_extension_init(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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* 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
@ -38,6 +38,7 @@
#include "6LoWPAN/Thread/thread_config.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_lowpower_private_api.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "6LoWPAN/Thread/thread_mle_message_handler.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_management_internal.h"
@ -48,13 +49,15 @@
#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"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "MLE/mle.h"
#include "mac_api.h"
#define TRACE_GROUP "thmh"
static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64);
static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor);
static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mac_neighbor_table_entry_t *neighbor);
static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
@ -72,11 +75,7 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg,
* and MUST be discarded.
*/
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
/* Check that message is from link-local scope */
if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
@ -100,11 +99,11 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg,
}
case MLE_COMMAND_REJECT: {
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
tr_warn("Reject Link");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
mle_class_remove_entry(cur->id, entry_temp);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
}
break;
}
@ -159,16 +158,11 @@ static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread
requestNetworkdata = true;
}
if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) {
if (!thread_partition_match(cur, leaderData)) {
requestNetworkdata = true;
thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1;
thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1;
thread_partition_info_update(cur, leaderData);
}
thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId;
thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId;
thread_info(cur)->thread_leader_data->weighting = leaderData->weighting;
if (requestNetworkdata) {
thread_bootstrap_parent_network_data_request(cur, false);
} else {
@ -215,12 +209,12 @@ static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, ui
return 0;
}
static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor)
static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mac_neighbor_table_entry_t *neighbor)
{
int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv);
if (leaderDataUpdate == 1) {
if (neighbor && neighbor->handshakeReady == 1) {
if (neighbor && neighbor->connected_device == 1) {
// Request network data if we have a 2-way link
tr_debug("Request New Network Data from %s", trace_ipv6(src_address));
thread_network_data_request_send(cur, src_address, true);
@ -272,30 +266,32 @@ static bool thread_router_advertiment_tlv_analyze(uint8_t *ptr, uint16_t data_le
return true;
}
static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mle_neigh_table_entry_t *entry_temp, uint16_t short_address)
static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mac_neighbor_table_entry_t *entry_temp, uint16_t short_address)
{
if (!entry_temp) {
return;
}
uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) {
mle_entry_timeout_refresh(entry_temp);
} else {
entry_temp->last_contact_time = protocol_core_monotonic_time;
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime);
}
if (short_address != entry_temp->short_adr) {
if (thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) {
if (short_address != entry_temp->mac16) {
if (thread_router_addr_from_addr(entry_temp->mac16) == cur->thread_info->routerShortAddress) {
thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16);
}
entry_temp->short_adr = short_address;
entry_temp->mac16 = short_address;
/* throw MLME_GET request, short address is changed automatically in get request callback */
mlme_get_t get_req;
get_req.attr = macDeviceTable;
get_req.attr_index = entry_temp->attribute_index;
get_req.attr_index = entry_temp->index;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
}
@ -304,11 +300,6 @@ static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_me
static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address)
{
if ((thread_info(cur)->thread_leader_data->partitionId != leader_data->partitionId) ||
(thread_info(cur)->thread_leader_data->weighting != leader_data->weighting)) {
//parent changed partition/weight - reset own routing information
thread_old_partition_data_purge(cur);
}
//check if network data needs to be requested
if (!thread_bootstrap_request_network_data(cur, leader_data, short_address)) {
tr_debug("Parent short address changed - re-attach");
@ -323,7 +314,7 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
{
mle_tlv_info_t routeTlv;
thread_leader_data_t leaderData;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
uint16_t shortAddress;
bool adv_from_my_partition;
bool my_parent;
@ -342,12 +333,16 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
}
// Get MLE entry
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
}
// Check if this is from my parent
my_parent = thread_check_is_this_my_parent(cur, entry_temp);
adv_from_my_partition = thread_instance_id_matches(cur, &leaderData);
adv_from_my_partition = thread_partition_match(cur, &leaderData);
if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) {
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
@ -355,13 +350,14 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
if (entry_temp && !adv_from_my_partition && !my_parent ) {
// Remove MLE entry that are located in other partition and is not my parent
mle_class_remove_entry(cur->id, entry_temp);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
entry_temp = NULL;
}
/* Check parent status */
if (!thread_attach_active_router(cur) && my_parent) {
if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
return;
}
}
@ -374,7 +370,7 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
/* REED and FED */
if (!thread_attach_active_router(cur)) {
/* Check if advertisement is from same partition */
if (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId ) {
if (thread_partition_match(cur, &leaderData)) {
if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
// Create link to new neighbor no other processing allowed
thread_link_request_start(cur, mle_msg->packet_src_address);
@ -404,9 +400,8 @@ static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle
}
// Process route TLV
if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) &&
(thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){
tr_debug("Update Route TLV %x", entry_temp->short_adr);
if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) && thread_partition_match(cur, &leaderData)){
tr_debug("Update Route TLV %x", entry_temp->mac16);
thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp);
}
}
@ -417,7 +412,7 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
uint16_t version, shortAddress;
uint16_t messageId;
uint8_t linkMarginfronNeigh;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
bool createNew, new_entry_created;
tr_info("MLE LINK ACCEPT");
@ -444,12 +439,14 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
/* Call to determine whether or not we should create a new link */
createNew = thread_bootstrap_link_create_check(cur, shortAddress);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry_created);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, createNew, &new_entry_created);
if (!entry_temp) {
thread_link_reject_send(cur, mle_msg->packet_src_address);
return;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, new_entry_created);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
@ -460,32 +457,35 @@ static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_messag
mleFrameCounter = llFrameCounter;
}
entry_temp->threadNeighbor = true;
entry_temp->short_adr = shortAddress;
entry_temp->mle_frame_counter = mleFrameCounter;
entry_temp->mac16 = shortAddress;
mle_service_frame_counter_entry_add(cur->id, entry_temp->index, mleFrameCounter);
// Set full data as REED needs full data and SED will not make links
entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index, true);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,llFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, security_headers->KeyIndex, new_entry_created);
uint32_t timeout;
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry_created);
if (entry_temp->timeout_rx) {
mle_entry_timeout_refresh(entry_temp);
if (new_entry_created) {
timeout = THREAD_DEFAULT_LINK_LIFETIME;
} else {
mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
timeout = entry_temp->link_lifetime;
}
if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->mac16)) {
// If we both are routers, mark the link as 2-way
entry_temp->handshakeReady = 1;
tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady);
entry_temp->connected_device = 1;
tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->connected_device);
} else {
tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady);
tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->connected_device);
}
blacklist_update(mle_msg->packet_src_address, true);
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
thread_routing_update_link_margin(cur, entry_temp->mac16, linkMargin, linkMarginfronNeigh);
}
}
static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg)
@ -544,7 +544,7 @@ static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle
mle_tlv_info_t ConfigurationTlv;
uint64_t active_timestamp = 0;
uint64_t pending_timestamp = 0;// means no pending timestamp
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
bool accept_new_data = false;
bool leaderDataReceived;
@ -560,7 +560,12 @@ static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle
return;
}
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
}
if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ||
cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
@ -570,7 +575,7 @@ static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle
return;
}
} else {
if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
if (!thread_partition_match(cur, &leaderData)) {
// if receiving data response from different partition it is dropped
return;
}
@ -583,10 +588,8 @@ static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle
}
}
if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
thread_old_partition_data_purge(cur);
if (!thread_partition_match(cur, &leaderData)) {
thread_partition_info_update(cur, &leaderData);
accept_new_data = true;
}
@ -705,11 +708,11 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent
mle_tlv_info_t tlv_req;
uint64_t active_timestamp = 0;
uint64_t pending_timestamp = 0;// means no pending timestamp
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
bool data_request_needed = false;
tr_debug("Child update request");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) ||
!entry_temp ||
@ -718,14 +721,16 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent
tr_warn("invalid message");
return;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
// Check if partition changed
if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
thread_old_partition_data_purge(cur);
if (!thread_partition_match(cur, &leaderData)) {
thread_partition_info_update(cur, &leaderData);
}
//Check Network Data TLV
if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
@ -767,7 +772,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
{
uint8_t mode;
uint32_t timeout;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
thread_leader_data_t leaderData = {0};
uint8_t status;
bool leader_data_received;
@ -780,11 +785,12 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
//mle_service_buffer_find
leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) &&
status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) {
tr_debug("parent has connection error");
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
return;
}
@ -798,6 +804,8 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
}
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
} else {
tr_debug("Key ID Mode 2 not used; dropped.");
@ -811,13 +819,11 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
timeout = cur->thread_info->host_link_timeout;
if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
entry_temp->holdTime = 90;
tr_debug("Setting child timeout, value=%"PRIu32, timeout);
mle_entry_timeout_update(entry_temp, timeout);
}
tr_debug("Keep-Alive -->Respond from Parent");
mle_entry_timeout_refresh(entry_temp);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
//Save possible new Leader Data
if (leader_data_received) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -50,6 +50,7 @@
#include "ns_trace.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_routing.h"
#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"
@ -57,6 +58,7 @@
#include "6LoWPAN/Thread/thread_resolution_server.h"
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
#include "6LoWPAN/Thread/thread_extension_bbr.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "Common_Protocols/icmpv6.h"
#include "MLE/mle.h"
@ -196,14 +198,14 @@ bool thread_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_
}
}
static mle_neigh_table_entry_t *thread_nd_child_mleid_get(int8_t interface_id, uint8_t *childAddress, uint8_t *mlmeid_ptr)
static mac_neighbor_table_entry_t *thread_nd_child_mleid_get(protocol_interface_info_entry_t *cur, uint8_t *childAddress, uint8_t *mlmeid_ptr)
{
mle_neigh_table_entry_t *entry_temp;
entry_temp = mle_class_get_by_link_address(interface_id, childAddress, ADDR_802_15_4_SHORT);
if (entry_temp) {
if ((entry_temp->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
memcpy(mlmeid_ptr,entry_temp->mlEid,8);
return entry_temp;
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), childAddress, ADDR_802_15_4_SHORT);
if (entry && !entry->ffd_device) {
uint8_t *ptr = thread_neighbor_class_get_mleid(&cur->thread_info->neighbor_class, entry->index);
if (ptr) {
memcpy(mlmeid_ptr, ptr, 8);
return entry;
}
}
return NULL;
@ -228,12 +230,13 @@ static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t tar
/* Scan IPv6 neighbour cache for registered entries of children */
ns_list_foreach(ipv6_neighbour_t, n, &cur->ipv6_neighbour_cache.list) {
if (n->type == IP_NEIGHBOUR_REGISTERED && addr_ipv6_equal(n->ip_address, target_addr)) {
mle_neigh_table_entry_t *mle_entry;
mac_neighbor_table_entry_t *mle_entry;
*addr_out = mac16;
mle_entry = thread_nd_child_mleid_get(interface_id, &n->ll_address[2], mleid_ptr);
mle_entry = thread_nd_child_mleid_get(cur, &n->ll_address[2], mleid_ptr);
if (mle_entry) {
//Get MLEID from Child
*last_transaction_time = (protocol_core_monotonic_time - mle_entry->last_contact_time) / 10; /* Both variables are count of 100ms ticks. */
uint32_t last_contact = thread_neighbor_last_communication_time_get(&cur->thread_info->neighbor_class, mle_entry->index);
*last_transaction_time = (protocol_core_monotonic_time - last_contact) / 10; /* Both variables are count of 100ms ticks. */
*proxy = true;
return 0;
}
@ -291,17 +294,18 @@ 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_address_generate(cur);
}
/* Scan IPv6 neighbour cache for registered entries of children */
ns_list_foreach_safe(ipv6_neighbour_t, n, &cur->ipv6_neighbour_cache.list) {
if (n->type == IP_NEIGHBOUR_REGISTERED && addr_ipv6_equal(n->ip_address, ip_addr)) {
uint8_t child_mleid[8];
mle_neigh_table_entry_t *child = thread_nd_child_mleid_get(interface_id, &n->ll_address[2], child_mleid);
mac_neighbor_table_entry_t *child = thread_nd_child_mleid_get(cur, &n->ll_address[2], child_mleid);
/* If this address belongs to an RFD child, with a different ML-EID, we must send it a duplicate message, and remove the EID */
if (child && memcmp(child_mleid, ml_eid, 8)) {
uint8_t child_ml_addr[16];
thread_addr_write_mesh_local_16(child_ml_addr, child->short_adr, cur->thread_info);
thread_addr_write_mesh_local_16(child_ml_addr, child->mac16, cur->thread_info);
tr_warn("Forwarding address error to child %04x", common_read_16_bit(&n->ll_address[2]));
thread_resolution_client_address_error(interface_id, child_ml_addr, ip_addr, ml_eid);
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, n);
@ -367,7 +371,7 @@ buffer_t *thread_nd_snoop(protocol_interface_info_entry_t *cur, buffer_t *buf, c
return buffer_free(buf);
}
if (!mle_class_get_by_link_address(cur->id, &ll_dst->address[2], ADDR_802_15_4_SHORT)) {
if (!mac_neighbor_table_address_discover(mac_neighbor_info(cur), &ll_dst->address[2], ADDR_802_15_4_SHORT)) {
/* We now know this was a packet for a non-existent child */
goto bounce;
}
@ -433,7 +437,7 @@ buffer_t *thread_nd_special_forwarding(protocol_interface_info_entry_t *cur, buf
return buf;
}
mle_neigh_table_entry_t *entry = mle_class_get_by_link_address(cur->id, &ll_src->address[2], ADDR_802_15_4_SHORT);
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), &ll_src->address[2], ADDR_802_15_4_SHORT);
/* Due to note 1 and 1b above, full-function children / neighbor routers
* who did resolve to an RLOC16 may have optimised out the mesh header.
@ -446,7 +450,7 @@ buffer_t *thread_nd_special_forwarding(protocol_interface_info_entry_t *cur, buf
* is not in our neighbour cache, we need to send the child an error
* to clear its cache.)
*/
if (!(buf->options.lowpan_mesh_rx || (entry && (entry->mode & MLE_DEV_MASK) == MLE_FFD_DEV))) {
if (!(buf->options.lowpan_mesh_rx || (entry && entry->ffd_device))) {
return buf;
}
@ -530,10 +534,11 @@ buffer_t *thread_nd_icmp_handler(protocol_interface_info_entry_t *cur, buffer_t
return buf;
}
int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const uint8_t *ipv6Address, uint16_t mac16, uint16_t panId, const uint8_t *mac64)
int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const uint8_t *ipv6Address, uint16_t mac16, uint16_t panId, const uint8_t *mac64, bool *new_neighbour_created)
{
ipv6_neighbour_t *neigh;
uint8_t ll_address[4];
bool neighbor_created = false;
common_write_16_bit(panId, ll_address + 0);
common_write_16_bit(mac16, ll_address + 2);
neigh = ipv6_neighbour_lookup_or_create(&cur->ipv6_neighbour_cache, ipv6Address);
@ -542,21 +547,24 @@ int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const u
}
uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh);
/*if (neigh->state != IP_NEIGHBOUR_NEW)
if (neigh->state != IP_NEIGHBOUR_NEW && memcmp(nce_eui64, mac64, 8) != 0)
{
// Worry about this later
// Compare mac64 to nce_eui64 to spot duplicates
return -2;
}
else*/
{
/* New entry */
memcpy(nce_eui64, mac64, 8);
if (neigh->state == IP_NEIGHBOUR_NEW) {
neighbor_created = true;
}
memcpy(nce_eui64, mac64, 8);
/* Set the LL address, ensure it's marked STALE */
ipv6_neighbour_entry_update_unsolicited(&cur->ipv6_neighbour_cache, neigh, ADDR_802_15_4_SHORT, ll_address);
neigh->type = IP_NEIGHBOUR_REGISTERED;
neigh->lifetime = 0xffffffff; //Set Infinite
ipv6_neighbour_set_state(&cur->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
if (new_neighbour_created) {
*new_neighbour_created = neighbor_created;
}
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -55,7 +55,7 @@ int thread_nd_map_anycast_address(protocol_interface_info_entry_t *cur, uint16_t
void thread_nd_address_remove(protocol_interface_info_entry_t *cur_interface, addrtype_t ll_type, const uint8_t *ll_address);
void thread_nd_flush_neighbour_cache_for_short_addr(struct protocol_interface_info_entry *cur, uint16_t flushee, bool children);
int thread_nd_address_registration(struct protocol_interface_info_entry *cur, const uint8_t *ipv6Address, uint16_t mac16, uint16_t panId, const uint8_t *mac64);
int thread_nd_address_registration(struct protocol_interface_info_entry *cur, const uint8_t *ipv6Address, uint16_t mac16, uint16_t panId, const uint8_t *mac64, bool *new_neighbour_created);
#else //HAVE_THREAD_NEIGHBOR_DISCOVERY

View File

@ -0,0 +1,209 @@
/*
* Copyright (c) 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 <string.h>
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "common_functions.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_routing.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
static thread_neigh_table_entry_t * thread_neighbor_class_table_entry_get(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
if (!class_ptr->neigh_info_list || attribute_index >= class_ptr->list_size) {
return NULL;
}
thread_neigh_table_entry_t *entry = class_ptr->neigh_info_list + attribute_index;
return entry;
}
bool thread_neighbor_class_create(thread_neighbor_class_t *class_ptr, uint8_t neigh_table_size)
{
class_ptr->neigh_info_list = ns_dyn_mem_alloc(sizeof(thread_neigh_table_entry_t) * neigh_table_size);
if (!class_ptr->neigh_info_list) {
return false;
}
class_ptr->list_size = neigh_table_size;
thread_neigh_table_entry_t * list_ptr = class_ptr->neigh_info_list;
for (uint8_t i = 0; i< neigh_table_size; i++) {
memset(list_ptr, 0, sizeof(thread_neigh_table_entry_t));
list_ptr++;
}
return true;
}
void thread_neighbor_class_delete(thread_neighbor_class_t *class_ptr)
{
ns_dyn_mem_free(class_ptr->neigh_info_list);
class_ptr->neigh_info_list = NULL;
class_ptr->list_size = 0;
}
void thread_neighbor_class_add_mleid(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, const uint8_t *mleid)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return;
}
memcpy(entry->mlEid, mleid, 8);
}
uint8_t * thread_neighbor_class_get_mleid(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return NULL;
}
return entry->mlEid;
}
void thread_neighbor_last_communication_time_update(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return;
}
entry->last_contact_time = protocol_core_monotonic_time;
}
void thread_neighbor_class_update_link(thread_neighbor_class_t *class_ptr, uint8_t attribute_index, uint8_t linkmargin, bool new_link)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return;
}
if (new_link) {
entry->link_margin = entry->link_margin + linkmargin - (entry->link_margin >> THREAD_LINK_MARGIN_SCALING);
} else {
entry->link_margin = linkmargin << THREAD_LINK_MARGIN_SCALING;
}
}
uint16_t thread_neighbor_entry_linkmargin_get(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return 0;
}
return entry->link_margin;
}
uint32_t thread_neighbor_last_communication_time_get(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return 0;
}
return entry->last_contact_time;
}
bool thread_neighbor_class_mleid_compare(thread_neighbor_class_t *class_ptr, uint8_t attribute_index, const uint8_t *mleid)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry || memcmp(entry->mlEid, mleid, 8)) {
return false;
}
return true;
}
bool thread_neighbor_class_request_full_data_setup(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return false;
}
return entry->request_full_data_set;
}
bool thread_neighbor_class_secured_data_request(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (!entry) {
return false;
}
return entry->secured_data_request;
}
void thread_neighbor_class_request_full_data_setup_set(thread_neighbor_class_t *class_ptr, uint8_t attribute_index, bool value)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (entry) {
entry->request_full_data_set = value;
}
}
void thread_neighbor_class_secured_data_request_set(thread_neighbor_class_t *class_ptr, uint8_t attribute_index, bool value)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (entry) {
entry->secured_data_request = value;
}
}
void thread_neighbor_class_mode_parse_to_entry(thread_neighbor_class_t *class_ptr, uint8_t attribute_index, uint8_t mode)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (entry) {
entry->request_full_data_set = mode & MLE_THREAD_REQ_FULL_DATA_SET;
entry->secured_data_request = mode & MLE_THREAD_SECURED_DATA_REQUEST;
}
}
uint8_t thread_neighbor_class_mode_write_from_entry(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
uint8_t mode = 0;
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (entry) {
if (entry->request_full_data_set) {
mode |= MLE_THREAD_REQ_FULL_DATA_SET;
}
if (entry->secured_data_request) {
mode |= MLE_THREAD_SECURED_DATA_REQUEST;
}
}
return mode;
}
void thread_neighbor_class_entry_remove(thread_neighbor_class_t *class_ptr, uint8_t attribute_index)
{
thread_neigh_table_entry_t *entry = thread_neighbor_class_table_entry_get(class_ptr,attribute_index);
if (entry) {
memset(entry, 0, sizeof(thread_neigh_table_entry_t));
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 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_NEIGHBOR_CLASS_H_
#define THREAD_NEIGHBOR_CLASS_H_
struct thread_neighbor_class_s;
/** Thead Spesific ModeFlags */
#define MLE_THREAD_SECURED_DATA_REQUEST 0x04
#define MLE_THREAD_REQ_FULL_DATA_SET 0x01
bool thread_neighbor_class_create(struct thread_neighbor_class_s *class_ptr, uint8_t neigh_table_size);
void thread_neighbor_class_delete(struct thread_neighbor_class_s *class_ptr);
void thread_neighbor_class_add_link(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, uint8_t linkmargin);
void thread_neighbor_class_add_mleid(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, const uint8_t *mleid);
uint8_t * thread_neighbor_class_get_mleid(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
void thread_neighbor_class_update_link(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, uint8_t linkmargin, bool new_link);
void thread_neighbor_last_communication_time_update(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
uint16_t thread_neighbor_entry_linkmargin_get(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
uint32_t thread_neighbor_last_communication_time_get(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
bool thread_neighbor_class_mleid_compare(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, const uint8_t *mleid);
bool thread_neighbor_class_request_full_data_setup(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
bool thread_neighbor_class_secured_data_request(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
void thread_neighbor_class_mode_parse_to_entry(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, uint8_t mode);
uint8_t thread_neighbor_class_mode_write_from_entry(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
void thread_neighbor_class_request_full_data_setup_set(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, bool value);
void thread_neighbor_class_secured_data_request_set(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index, bool value);
void thread_neighbor_class_entry_remove(struct thread_neighbor_class_s *class_ptr, uint8_t attribute_index);
#endif /* THREAD_NEIGHBOR_CLASS_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -60,6 +60,7 @@
#define THREAD_P_DEF_ROUTE_BIT_MOVE 9 /* R-bit */
#define THREAD_P_ON_MESH_BIT_MOVE 8 /* O-bit */
#define THREAD_P_ND_DNS_BIT_MOVE 7 /* N-bit */
#define THREAD_P_ND_RES_BIT_MOVE 6 /* First reserved bit */
/* Bit shift for HasRouteTLV preference bit */
#define THREAD_HAS_ROUTE_PRF_BIT_MOVE 6 /* Prf-bits */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -328,9 +328,8 @@ thread_network_local_data_entry_t *thread_local_service_list_allocate(thread_pre
newEntry->servicesPrefixLen = prefixTlv->PrefixLen;
newEntry->domainId = prefixTlv->domainId;
newEntry->dhcpv6ServerActive = false;
newEntry->dhcpv6ServerDataStable = false;
newEntry->brDataStable = false;
newEntry->slaacServerActive = false;
newEntry->slaacServerDataStable = false;
newEntry->slaacPreferred = false;
newEntry->routeActive = false;
newEntry->routeDataStable = false;
@ -339,6 +338,8 @@ thread_network_local_data_entry_t *thread_local_service_list_allocate(thread_pre
newEntry->defaultRoute = false;
newEntry->onMesh = false;
newEntry->ndDns = false;
newEntry->brActive = false;
newEntry->res1 = false;
}
return newEntry;
}
@ -373,6 +374,7 @@ thread_network_server_data_entry_t *thread_server_entry_allocate(thread_border_r
newEntry->Prf = service->Prf;
newEntry->P_on_mesh = service->P_on_mesh;
newEntry->P_nd_dns = service->P_nd_dns;
newEntry->P_res1 = service->P_res1;
newEntry->canDelete = false;
}
@ -868,7 +870,7 @@ static int thread_service_data_delete_mark_by_router_id(thread_network_data_serv
return retVal;
}
static int thread_server_context_clean(thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list)
static int thread_server_context_clean(int8_t id, thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list)
{
int retVal = -1;
(void) prefixEntry;
@ -879,7 +881,9 @@ static int thread_server_context_clean(thread_network_data_cache_entry_t *cacheP
cachePtr->stableUpdatePushed = true;
}
// Set context lifetime to 0 to delete
if (thread_extension_context_can_delete(id, prefixEntry->servicesPrefix, cur->contextPrefixLength)) {
lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true);
}
ns_list_remove(listPtr, cur);
ns_dyn_mem_free(cur);
retVal = 0;
@ -1019,7 +1023,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache
}
thread_server_data_clean_by_router_id(cachePtr, &cur->routeList, cur, true, curInterface);
if (!is_leader) {
thread_server_context_clean(cachePtr, &cur->contextList, cur, &curInterface->lowpan_contexts);
thread_server_context_clean(curInterface->id, cachePtr, &cur->contextList, cur, &curInterface->lowpan_contexts);
}
if (ns_list_is_empty(&cur->borderRouterList)) {
@ -1071,7 +1075,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache
return address_removed;
}
void thread_network_data_context_re_use_timer_update(thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list)
void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list)
{
ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList) {
ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) {
@ -1086,7 +1090,9 @@ void thread_network_data_context_re_use_timer_update(thread_network_data_cache_e
cachePtr->temporaryUpdatePushed = true;
}
// Set context lifetime to 0 to delete
if (thread_extension_context_can_delete(id, cur->servicesPrefix,curContext->contextPrefixLength)) {
lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true);
}
ns_dyn_mem_free(curContext);
}
}
@ -1708,21 +1714,21 @@ int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_
if (networkDataList) {
thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv);
if (prefix_entry) {
prefix_entry->brDataStable = service->stableData;
prefix_entry->preference = service->Prf;
prefix_entry->configure = service->P_configure;
prefix_entry->defaultRoute = service->P_default_route;
prefix_entry->onMesh = service->P_on_mesh;
prefix_entry->ndDns = service->P_nd_dns;
if (service->P_dhcp) {
prefix_entry->dhcpv6ServerActive = true;
prefix_entry->dhcpv6ServerDataStable = service->stableData;
}
if (service->P_slaac) {
prefix_entry->slaacServerActive = true;
prefix_entry->slaacServerDataStable = service->stableData;
prefix_entry->res1 = service->P_res1;
prefix_entry->dhcpv6ServerActive = service->P_dhcp;
prefix_entry->slaacServerActive = service->P_slaac;
prefix_entry->slaacPreferred = service->P_preferred;
if (service->P_dhcp ||
service->P_slaac ||
service->P_res1) {
prefix_entry->brActive = true;
}
if (prefixTlv->PrefixLen == 0) {
@ -1891,9 +1897,7 @@ int thread_local_server_del_route(thread_network_local_data_cache_entry_t *netwo
}
prefix_entry->routeActive = false;
if (prefix_entry->dhcpv6ServerActive) {
return 0;
} else if (prefix_entry->slaacServerActive) {
if (prefix_entry->brActive) {
return 0;
}
@ -2023,17 +2027,13 @@ uint8_t thread_server_prefix_length(thread_network_local_data_entry_t *cur)
if (cur->routeActive) {
if (!((cur->slaacServerActive || cur->dhcpv6ServerActive) && cur->defaultRoute)) {
if (!(cur->brActive && cur->defaultRoute)) {
// HasRoute is added if BorderRouter TLV does not have default route bit
tempLength += 5;
}
}
if (cur->dhcpv6ServerActive) {
tempLength += 6;
}
if (cur->slaacServerActive) {
if (cur->brActive) {
tempLength += 6;
}
@ -2091,14 +2091,9 @@ uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_en
static bool thread_check_local_data_prefix_stable_boolean(thread_network_local_data_entry_t *dataList)
{
if (dataList->dhcpv6ServerActive && dataList->dhcpv6ServerDataStable) {
if (dataList->brActive && dataList->brDataStable) {
return true;
}
if (dataList->slaacServerActive && dataList->slaacServerDataStable) {
return true;
}
return false;
}
@ -2269,7 +2264,7 @@ uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_
if (servicesLen) {
ptr = thread_nd_hosted_prefix_header_write(ptr,servicesLen, cur);
if (cur->routeActive) {
if (!((cur->slaacServerActive || cur->dhcpv6ServerActive) && cur->defaultRoute)) {
if (!(cur->brActive && cur->defaultRoute)) {
// HasRoute is added if BorderRouter TLV does not have default route bit
uint8_t preference = 0;
tlvType = THREAD_NWK_DATA_TYPE_ROUTE;
@ -2283,10 +2278,10 @@ uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_
}
}
if (cur->slaacServerActive || cur->dhcpv6ServerActive) {
if (cur->brActive) {
uint16_t flags = 0;
tlvType = THREAD_NWK_DATA_TYPE_BORDER_ROUTER;
if (cur->slaacServerDataStable || cur->dhcpv6ServerDataStable) {
if (cur->brDataStable) {
tlvType |= THREAD_NWK_STABLE_DATA;
}
if (cur->slaacServerActive) {
@ -2313,6 +2308,9 @@ uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_
if (cur->ndDns) {
flags |= 1 << THREAD_P_ND_DNS_BIT_MOVE;
}
if (cur->res1) {
flags |= 1 << THREAD_P_ND_RES_BIT_MOVE;
}
ptr = thread_service_border_router_tlv_write(ptr, tlvType, routerID, flags);
} // slaac or dhcp
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -72,6 +72,7 @@ typedef struct thread_network_data_temporary_route_or_dhcpv6_server_entry_s {
bool stableData: 1;
bool P_on_mesh: 1;
bool P_nd_dns: 1;
bool P_res1: 1;
bool canDelete: 1;
ns_list_link_t link; /*!< List link entry */
} thread_network_server_data_entry_t;
@ -87,6 +88,7 @@ typedef struct thread_border_router_tlv_entry_t {
bool stableData: 1; /* P_stable */
bool P_on_mesh: 1; /* P_on_mesh */
bool P_nd_dns: 1; /* P_nd_dns */
bool P_res1: 1; /* P_res1 */
} thread_border_router_tlv_entry_t;
typedef struct thread_prefix_tlv {
@ -136,16 +138,17 @@ typedef struct thread_network_local_data_entry_s {
uint8_t servicesPrefixLen; /*!< Prefix length in bits This Can Be 1-128 */
bool routeActive: 1;
bool routeDataStable: 1;
bool brActive: 1;
bool dhcpv6ServerActive: 1;
bool dhcpv6ServerDataStable: 1;
bool brDataStable: 1;
bool slaacServerActive: 1;
bool slaacServerDataStable: 1;
bool slaacPreferred: 1;
unsigned preference: 2;
bool configure: 1;
bool defaultRoute: 1;
bool onMesh: 1;
bool ndDns: 1;
bool res1:1;
ns_list_link_t link; /*!< List link entry */
} thread_network_local_data_entry_t;
@ -207,7 +210,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache
void thread_network_local_data_free_and_clean(thread_network_local_data_cache_entry_t *cachePtr, int8_t interface_id);
void thread_network_data_context_re_use_timer_update(thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list);
void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list);
/**
* Add new route information to route List

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -56,12 +56,14 @@
#include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_management_client.h"
#include "6LoWPAN/Thread/thread_network_synch.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "thread_management_if.h"
#include "thread_config.h"
#include "Common_Protocols/ipv6.h"
#include "Common_Protocols/icmpv6.h"
#include "Common_Protocols/icmpv6_radv.h"
#include "MLE/mle.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#define TRACE_GROUP "tsyn"
@ -90,7 +92,7 @@ typedef struct thread_network_dynamic_data_entry {
} thread_network_dynamic_data_entry_t;
static thread_sync_child_info_t *thread_dynamic_storage_free_child_find(int8_t interface_id);
static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mle_neigh_table_entry_t *child);
static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mac_neighbor_table_entry_t *child);
static NS_LIST_DEFINE(thread_network_dynamic_data_info, thread_network_dynamic_data_entry_t, link);
thread_network_dynamic_data_entry_t *thread_network_synch_create(int8_t interfaceId)
@ -155,54 +157,53 @@ int thread_network_synch_data_free(int8_t interface_id)
* Dynamic network data storage.
*/
void thread_dynamic_storage_child_info_store(int8_t interface_id, mle_neigh_table_entry_t *child)
void thread_dynamic_storage_child_info_store(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *child)
{
thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(cur_interface->id);
if (!storeEntry) {
storeEntry = thread_network_synch_create(interface_id);
storeEntry = thread_network_synch_create(cur_interface->id);
}
if (!storeEntry) {
return;
}
thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(interface_id, child);
uint32_t mle_frame_counter = mle_service_neighbor_frame_counter_get(cur_interface->id, child->index);
thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(cur_interface->id, child);
if (!child_info) {
child_info = thread_dynamic_storage_free_child_find(cur_interface->id);
}
if (child_info) {
child_info->mode = child->mode;
child_info->short_addr = child->short_adr;
child_info->mle_frame_counter = child->mle_frame_counter;
uint8_t mode = mle_mode_write_from_mac_entry(child);
mode |= thread_neighbor_class_mode_write_from_entry(&cur_interface->thread_info->neighbor_class, child->index);
child_info->mode = mode;
child_info->short_addr = child->mac16;
child_info->mle_frame_counter = mle_frame_counter;
child_info->mac_frame_counter = 0;
memcpy(child_info->long_addr, child->mac64, 8);
return;
}
child_info = thread_dynamic_storage_free_child_find(interface_id);
if (child_info) {
child_info->mode = child->mode;
child_info->short_addr = child->short_adr;
child_info->mle_frame_counter = child->mle_frame_counter;
child_info->mac_frame_counter = 0;
memcpy(child_info->long_addr, child->mac64, 8);
}
return;
}
void thread_dynamic_storage_child_info_clear(int8_t interface_id, mle_neigh_table_entry_t *child)
void thread_dynamic_storage_child_info_clear(int8_t interface_id, struct mac_neighbor_table_entry *child)
{
thread_sync_child_info_t *child_info = thread_dynamic_storage_child_info_find(interface_id, child);
if (child_info){
// Clear child information
memset (child_info,0,sizeof(thread_sync_child_info_t));
tr_debug("Dynamic storage: cleared child; mac16=%04x", child->short_adr);
tr_debug("Dynamic storage: cleared child; mac16=%04x", child->mac16);
return;
}
return;
}
static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mle_neigh_table_entry_t *child)
static thread_sync_child_info_t *thread_dynamic_storage_child_info_find(int8_t interface_id, mac_neighbor_table_entry_t *child)
{
thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
@ -236,6 +237,10 @@ static thread_sync_child_info_t *thread_dynamic_storage_free_child_find(int8_t i
void thread_dynamic_storage_build_mle_table(int8_t interface_id)
{
tr_debug("Dynamic storage: building MLE table.");
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_parameters) {
return;
}
thread_network_dynamic_data_entry_t *storeEntry = thread_network_synch_find(interface_id);
bool new_entry_created;
@ -248,9 +253,9 @@ void thread_dynamic_storage_build_mle_table(int8_t interface_id)
return;
}
mle_neigh_table_list_t *neig_list = mle_class_active_list_get(interface_id);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
if (!neig_list) {
if (!mac_table_list) {
return;
}
@ -262,19 +267,21 @@ void thread_dynamic_storage_build_mle_table(int8_t interface_id)
}
uint8_t *mac64 = storeEntry->networ_dynamic_data_parameters.children[i].long_addr;
tr_debug("Child: %04x, %s", storeEntry->networ_dynamic_data_parameters.children[i].short_addr, trace_array(mac64, 8));
mle_neigh_table_entry_t *entry = mle_class_get_entry_by_mac64(interface_id, 64, mac64, true, &new_entry_created);
if (entry) {
entry->short_adr = storeEntry->networ_dynamic_data_parameters.children[i].short_addr;
entry->mle_frame_counter = storeEntry->networ_dynamic_data_parameters.children[i].mle_frame_counter;
entry->mode = storeEntry->networ_dynamic_data_parameters.children[i].mode;
entry->threadNeighbor = true;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(cur), mac64, true, &new_entry_created);
if (mac_entry) {
mac_entry->mac16 = storeEntry->networ_dynamic_data_parameters.children[i].short_addr;
mle_service_frame_counter_entry_add(interface_id, mac_entry->index, storeEntry->networ_dynamic_data_parameters.children[i].mle_frame_counter);
mle_mode_parse_to_mac_entry(mac_entry, storeEntry->networ_dynamic_data_parameters.children[i].mode);
if (cur && cur->mac_parameters) {
// Set MAC layer frame counter for the child
mac_helper_devicetable_set(entry, cur, storeEntry->networ_dynamic_data_parameters.children[i].mac_frame_counter, cur->mac_parameters->mac_default_key_index, new_entry_created);
}
mlme_device_descriptor_t device_desc;
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, mac_entry->index,64, new_entry_created);
thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, mac_entry->index,storeEntry->networ_dynamic_data_parameters.children[i].mode);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, mac_entry->index);
mac_helper_device_description_write(cur, &device_desc, mac_entry->mac64, mac_entry->mac16,storeEntry->networ_dynamic_data_parameters.children[i].mac_frame_counter, false);
mac_helper_devicetable_set(&device_desc, cur, mac_entry->index, cur->mac_parameters->mac_default_key_index, new_entry_created);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -35,6 +35,9 @@
#ifndef THREAD_NETWORK_SYNCH_H_
#define THREAD_NETWORK_SYNCH_H_
struct protocol_interface_info_entry;
struct mac_neighbor_table_entry;
//Call This when clean synched networkdata
int thread_network_synch_data_free(int8_t interface_id);
//Call This when want synch last network setup
@ -46,8 +49,8 @@ bool thread_dynamic_storage_pending_configuration_exists(int8_t interface_id);
void thread_dynamic_storage_pending_configuration_read(int8_t interface_id, void *data, uint16_t size);
void thread_dynamic_storage_pending_configuration_store(int8_t interface_id, void *data, uint16_t size);
void thread_dynamic_storage_child_info_store(int8_t interface_id, mle_neigh_table_entry_t *child);
void thread_dynamic_storage_child_info_clear(int8_t interface_id, mle_neigh_table_entry_t *child);
void thread_dynamic_storage_child_info_store(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *child);
void thread_dynamic_storage_child_info_clear(int8_t interface_id, struct mac_neighbor_table_entry *child);
void thread_dynamic_storage_build_mle_table(int8_t interface_id);
void thread_dynamic_storage_frame_counter_store(int8_t interface_id, uint32_t mle_frame_counter, uint32_t mac_frame_counter);
uint32_t thread_dynamic_storage_mle_frame_counter_get(int8_t interfaceId);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -84,7 +84,7 @@ static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t* fast_data_to_
static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t seq_counter);
static void thread_nvm_store_link_info_delayed_write(uint32_t seconds);
#define MAX_ROOT_PATH_LEN 150
#define MAX_ROOT_PATH_LEN 200
#define FAST_DATA_STRING_LEN (strlen(FAST_DATA_FILE)+strlen(thread_nvm_store_get_root_path())+1)
#define ACTIVE_CONF_STRING_LEN (strlen(THREAD_NVM_ACTIVE_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1)
@ -330,6 +330,15 @@ int thread_nvm_store_fast_data_check_and_write(uint32_t mac_frame_counter, uint3
return ret;
}
int thread_nvm_store_fast_data_write_all(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter)
{
int ret;
ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter);
cached_fast_data.mac_frame_counter = mac_frame_counter;
cached_fast_data.mle_frame_counter = mle_frame_counter;
cached_fast_data.seq_counter=network_seq_counter;
return ret;
}
int thread_nvm_store_frame_counters_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* 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
@ -84,6 +84,9 @@ int thread_nvm_store_fast_data_write(thread_nvm_fast_data_t* fast_data);
int thread_nvm_store_frame_counters_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter);
/* stores the frame counter and seq counter to nvm only if any threshold is passed*/
int thread_nvm_store_fast_data_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter);
/*Store all fast data values unconditionally*/
int thread_nvm_store_fast_data_write_all(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter);
/* stores the value to nvm only if it has changed */
int thread_nvm_store_seq_counter_write(uint32_t network_seq_counter);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -66,6 +66,7 @@
#include "6LoWPAN/Thread/thread_lowpower_private_api.h"
#include "6LoWPAN/Thread/thread_tmfcop_lib.h"
#include "6LoWPAN/Thread/thread_nvm_store.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "thread_management_if.h"
#include "Common_Protocols/ipv6.h"
#include "Common_Protocols/icmpv6.h"
@ -83,12 +84,12 @@
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "thread_border_router_api.h"
#include "Core/include/address.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#ifdef HAVE_THREAD_ROUTER
#define TRACE_GROUP "trbs"
static bool thread_rfd_device(uint8_t mode);
static uint8_t *thread_tlv_add(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint8_t tlv_type, uint8_t mode);
static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf);
@ -103,18 +104,10 @@ static int thread_router_accept_request_build(protocol_interface_info_entry_t *c
static int thread_child_update_response(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t mode, uint16_t short_address, uint32_t timeout, mle_tlv_info_t *addressRegisterTlv,mle_tlv_info_t *tlvReq, mle_tlv_info_t *challengeTlv, uint64_t active_timestamp, uint64_t pending_timestamp);
static int mle_build_and_send_data_response_msg(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t *data_ptr, uint16_t data_len, mle_tlv_info_t *request_tlv, uint8_t mode);
static int thread_attach_parent_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, uint8_t *challenge, uint16_t chalLen, uint8_t linkMargin, uint8_t scanMask, uint8_t mode);
static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress,thread_pending_child_id_req_t *child_req,mle_neigh_table_entry_t *neigh_info);
static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress,thread_pending_child_id_req_t *child_req, struct mac_neighbor_table_entry *neigh_info);
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, mle_neigh_table_entry_t *entry_temp);
static bool thread_rfd_device(uint8_t mode)
{
if ((mode & MLE_DEV_MASK) != MLE_RFD_DEV) {
return false;
}
return true;
}
static bool thread_child_id_request(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *entry_temp);
static bool thread_router_parent_address_check(protocol_interface_info_entry_t *cur, uint8_t *source_addr)
{
@ -209,7 +202,7 @@ int thread_router_bootstrap_mle_advertise(protocol_interface_info_entry_t *cur)
}
static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *mle_entry, buffer_t *buf)
static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry, buffer_t *buf)
{
link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
if (!linkConfiguration) {
@ -224,7 +217,7 @@ static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mle
new_buf->info = (buffer_info_t) (B_DIR_DOWN | B_TO_IPV6_TXRX | B_FROM_IPV6_FWD);
uint8_t next_hop[16];
memcpy(next_hop, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(&next_hop[8], mle_entry->mac64, 8);
memcpy(&next_hop[8], entry->mac64, 8);
next_hop[8] ^= 2;
ipv6_buffer_route_to(new_buf, next_hop, cur);
@ -234,18 +227,14 @@ static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mle
static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf)
{
mle_neigh_table_list_t *mle_neigh_list = mle_class_active_list_get(cur->id);
if (!mle_neigh_list) {
return;
}
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_neigh_list) {
if (cur_entry->threadNeighbor) {
if (!(cur_entry->mode & MLE_RX_ON_IDLE)) {
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (!cur_entry->rx_on_idle) {
clone_multicast_to_unicast(cur, cur_entry, buf);
}
}
}
}
static void thread_multicast_forward_to_child(protocol_interface_info_entry_t *cur, buffer_t *buffer)
{
@ -260,9 +249,9 @@ static void thread_registered_mcast_forward_to_child(protocol_interface_info_ent
tr_debug("Forwarding to registered multicast address: %s", trace_ipv6(addr->address));
ns_list_foreach(thread_mcast_child_t, child, &addr->children) {
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, child->mac64, ADDR_802_15_4_LONG);
if (mle_entry && mle_entry->threadNeighbor && !(mle_entry->mode & MLE_RX_ON_IDLE)) {
clone_multicast_to_unicast(cur, mle_entry, buffer);
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), child->mac64, ADDR_802_15_4_LONG);
if (entry && !entry->rx_on_idle) {
clone_multicast_to_unicast(cur, entry, buffer);
}
}
}
@ -304,13 +293,10 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
uint16_t version, shortAddress, address16;
uint32_t llFrameCounter;
mle_tlv_info_t routing;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
tr_debug("Thread MLE message router sync");
//State machine What packet shuold accept in this case
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
/* Check that message is from link-local scope */
if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
@ -353,42 +339,56 @@ static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *m
return;
}
//Allocate neighbor entry
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, true, &new_neigbour);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, &new_neigbour);
if (!entry_temp) {
return;
}
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
thread_key_guard_timer_reset(cur);
} else {
tr_error("Key ID Mode 2 not used; dropped.");
return;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, new_neigbour);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
//Free Response
mle_service_msg_free(messageId);
entry_temp->threadNeighbor = true;
entry_temp->short_adr = shortAddress;
entry_temp->mac16 = shortAddress;
//when allocating neighbour entry, use MLE Frame counter if present to validate further advertisements from the neighbour
entry_temp->mle_frame_counter = mleFrameCounter;
if (entry_temp->timeout_rx) {
mle_entry_timeout_refresh(entry_temp);
} else {
mle_tlv_info_t mle_tlv_info;
mle_service_frame_counter_entry_add(cur->id, entry_temp->index, mleFrameCounter);
uint32_t timeout_tlv;
mle_tlv_info_t mle_tlv_info;
if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_TIMEOUT, &mle_tlv_info) > 0) {
timeout_tlv = common_read_32_bit(mle_tlv_info.dataPtr);
mle_entry_timeout_update(entry_temp, timeout_tlv);
} else {
mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
if (new_neigbour) {
timeout_tlv = THREAD_DEFAULT_LINK_LIFETIME;
} else {
timeout_tlv = entry_temp->link_lifetime;
}
}
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout_tlv);
if (thread_is_router_addr(shortAddress)) {
entry_temp->handshakeReady = 1;
entry_temp->connected_device = 1;
}
entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index, true);
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
thread_routing_update_link_margin(cur, entry_temp->mac16, linkMargin, linkMarginfronNeigh);
}
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_neigbour);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,llFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, security_headers->KeyIndex, new_neigbour);
//Copy Leader Data
*cur->thread_info->thread_leader_data = leaderData;
@ -949,17 +949,17 @@ static int thread_attach_parent_response_build(protocol_interface_info_entry_t *
return 0;
}
int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *child)
int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child)
{
/* Cleanup occurs for /any/ link we lose to something that looks like a child address,
* not just links that are /now/ our children.
* Due to REED/partition transitions the address may not look like a current child address;
* we could be holding a child entry for future repromotion to router with same ID.
*/
if (thread_is_router_addr(child->short_adr) || child->short_adr >= 0xfffe) {
if (thread_is_router_addr(child->mac16) || child->mac16 >= 0xfffe) {
return -1;
}
tr_debug("Child free %x", child->short_adr);
tr_debug("Child free %x", child->mac16);
thread_dynamic_storage_child_info_clear(cur->id, child);
/* As we are losing a link to a child address, we can assume that if we have an IP neighbour cache
@ -967,12 +967,12 @@ int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cu
* finding a new parent, and hence a new 16-bit address. (Losing a link to a router address would not
* invalidate our IP->16-bit mapping.)
*/
protocol_6lowpan_release_short_link_address_from_neighcache(cur, child->short_adr);
protocol_6lowpan_release_short_link_address_from_neighcache(cur, child->mac16);
// If Child's RLOC16 appears in the Network Data send the RLOC16 to the Leader
if (thread_network_data_services_registered(&cur->thread_info->networkDataStorage, child->short_adr)) {
if (thread_network_data_services_registered(&cur->thread_info->networkDataStorage, child->mac16)) {
tr_debug("Remove references to Child's RLOC16 from the Network Data");
thread_management_client_network_data_unregister(cur->id, child->short_adr);
thread_management_client_network_data_unregister(cur->id, child->mac16);
}
// Clear all (sleepy) child registrations to multicast groups
@ -991,13 +991,11 @@ void thread_router_bootstrap_child_information_clear(protocol_interface_info_ent
}
// Remove mle neighbour entries for children in previous partition
mle_neigh_table_list_t *entry_list = mle_class_active_list_get(cur->id);
if (!entry_list) {
return;
}
ns_list_foreach_safe(mle_neigh_table_entry_t, table_entry, entry_list) {
if (table_entry->short_adr < 0xfffe && !thread_is_router_addr(table_entry->short_adr)) {
mle_class_remove_entry(cur->id, table_entry);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach_safe(mac_neighbor_table_entry_t, table_entry, mac_table_list) {
if (table_entry->mac16 < 0xfffe && !thread_is_router_addr(table_entry->mac16)) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), table_entry);
}
}
}
@ -1006,17 +1004,14 @@ static void thread_router_bootstrap_invalid_child_information_clear(protocol_int
tr_debug("Thread Short address changed old: %x new: %x", cur->thread_info->routerShortAddress, router_rloc);
mle_neigh_table_list_t *entry_list = mle_class_active_list_get(cur->id);
if (!entry_list) {
return;
}
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
// scrub neighbours with child addresses that are not ours
ns_list_foreach_safe(mle_neigh_table_entry_t, table_entry, entry_list) {
if (table_entry->short_adr < 0xfffe &&
!thread_is_router_addr(table_entry->short_adr) &&
thread_router_addr_from_addr(table_entry->short_adr) != router_rloc) {
mle_class_remove_entry(cur->id, table_entry);
ns_list_foreach_safe(mac_neighbor_table_entry_t, table_entry, mac_table_list) {
if (table_entry->mac16 < 0xfffe &&
!thread_is_router_addr(table_entry->mac16) &&
thread_router_addr_from_addr(table_entry->mac16) != router_rloc) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), table_entry);
}
}
}
@ -1105,7 +1100,7 @@ void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t *
}
}
static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress,thread_pending_child_id_req_t *child_req,mle_neigh_table_entry_t *neigh_info)
static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress,thread_pending_child_id_req_t *child_req, struct mac_neighbor_table_entry *neigh_info)
{
uint16_t len = 12 + 4; //Leader data and short address
uint8_t *ptr;
@ -1117,7 +1112,7 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c
return -1;
}
if (neigh_info->mode & MLE_THREAD_REQ_FULL_DATA_SET) {
if (thread_neighbor_class_request_full_data_setup(&cur->thread_info->neighbor_class, neigh_info->index)) {
fullList = true;
}
@ -1163,7 +1158,7 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c
ptr = mle_general_write_source_address(ptr, cur);
if (child_req->shortAddressReq) {
ptr = mle_tlv_write_short_address(ptr, neigh_info->short_adr);
ptr = mle_tlv_write_short_address(ptr, neigh_info->mac16);
}
if (child_req->routeReq) {
@ -1214,12 +1209,10 @@ uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t
if (router_address >= 0xfffe) {
return 0;
}
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
if (!mle_table) {
return -1;
}
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if (thread_router_addr_from_addr(cur_entry->short_adr) == router_address) {
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (thread_router_addr_from_addr(cur_entry->mac16) == router_address) {
child_count++;
}
}
@ -1228,22 +1221,19 @@ uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t
static uint16_t thread_router_bootstrap_child_address_generate(protocol_interface_info_entry_t *cur)
{
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
if (!mle_table) {
return -1;
}
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
if (thread_router_bootstrap_child_count_get(cur) >= cur->thread_info->maxChildCount) {
tr_info("Maximum count %d reached", cur->thread_info->maxChildCount);
return 0xffff;
return 0xfffe;
}
bool address_allocated = false;
for (uint16_t i = 0; i < cur->thread_info->maxChildCount; i++) {
address_allocated = false;
cur->thread_info->lastAllocatedChildAddress = (cur->thread_info->lastAllocatedChildAddress % THREAD_MAX_CHILD_ID_COUNT) + 1;
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if ( (cur_entry->short_adr & THREAD_CHILD_MASK) == cur->thread_info->lastAllocatedChildAddress) {
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if ( (cur_entry->mac16 & THREAD_CHILD_MASK) == cur->thread_info->lastAllocatedChildAddress) {
address_allocated = true;
break;
}
@ -1254,29 +1244,29 @@ static uint16_t thread_router_bootstrap_child_address_generate(protocol_interfac
}
if (address_allocated){
// all possible addresses already allocated
return 0xffff;
return 0xfffe;
}
return ((mac_helper_mac16_address_get(cur) & THREAD_ROUTER_MASK) | cur->thread_info->lastAllocatedChildAddress);
}
static bool thread_child_id_request(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp)
static bool thread_child_id_request(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *entry_temp)
{
//Remove All Short address links from router
if (entry_temp->short_adr != 0xffff) {
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
if (entry_temp->mac16 < 0xfffe) {
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16);
}
//allocate child address if current is router, 0xffff or not our child
if (!thread_addr_is_child(mac_helper_mac16_address_get(cur), entry_temp->short_adr)) {
entry_temp->short_adr = thread_router_bootstrap_child_address_generate(cur);
if (!thread_addr_is_child(mac_helper_mac16_address_get(cur), entry_temp->mac16)) {
entry_temp->mac16 = thread_router_bootstrap_child_address_generate(cur);
}
if (entry_temp->short_adr == 0xffff) {
if (entry_temp->mac16 >= 0xfffe) {
return false;
}
// Store this child info to the NVM
thread_dynamic_storage_child_info_store(cur->id, entry_temp);
thread_dynamic_storage_child_info_store(cur, entry_temp);
//}
return true;
}
@ -1311,7 +1301,7 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
memcpy(&ll64[8], req->euid64 , 8);
ll64[8] ^= 2;
//Allocate entry
mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, req->linkMargin, ll64, true, &new_neigbour);
mac_neighbor_table_entry_t *entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, true, &new_neigbour);
if (!entry_temp) {
//Send link reject
@ -1319,44 +1309,48 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
goto free_request;
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, req->linkMargin, new_neigbour);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
// If mac frame couter is less than previous we need to leave the old one
//Update or set neigh info
entry_temp->holdTime = 90;
mle_entry_timeout_update(entry_temp, req->timeout);
entry_temp->mode = req->mode;
entry_temp->threadNeighbor = true;
entry_temp->handshakeReady = 1;
entry_temp->mle_frame_counter = req->mleFrameCounter;
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, req->timeout);
mle_mode_parse_to_mac_entry(entry_temp, req->mode);
thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index, req->mode);
entry_temp->connected_device = 1;
mle_service_frame_counter_entry_add(cur->id, entry_temp->index, req->mleFrameCounter);
if (req->shortAddressReq) {
if (!thread_child_id_request(cur, entry_temp)) {
mle_class_remove_entry(cur->id, entry_temp);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
thread_link_reject_send(cur, ll64);
goto free_request;
}
}
if (new_neigbour) {
mac_helper_devicetable_set(entry_temp, cur, req->frameCounter, req->keyId, new_neigbour);
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,req->frameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, req->keyId, new_neigbour);
} else {
// in get response handler this will update the short address from MLE table
mlme_get_t get_req;
get_req.attr = macDeviceTable;
get_req.attr_index = entry_temp->attribute_index;
get_req.attr_index = entry_temp->index;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
}
//Register MLEID if RRFD device
if ((entry_temp->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
if (!entry_temp->ffd_device) {
uint8_t tempIPv6Address[16];
memcpy(tempIPv6Address, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8);
memcpy(&tempIPv6Address[8], req->eiid, 8);
memcpy(&entry_temp->mlEid, req->eiid, 8);
thread_neighbor_class_add_mleid(&cur->thread_info->neighbor_class, entry_temp->index, req->eiid);
tr_debug("Register %s", trace_ipv6(tempIPv6Address));
//Register GP --> 16
thread_nd_address_registration(cur, tempIPv6Address, entry_temp->short_adr, cur->mac_parameters->pan_id, entry_temp->mac64);
thread_nd_address_registration(cur, tempIPv6Address, entry_temp->mac16, cur->mac_parameters->pan_id, entry_temp->mac64, NULL);
}
mle_attach_child_id_response_build(cur,ll64,req, entry_temp);
@ -1371,6 +1365,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
lowpan_context_t *ctx;
uint8_t tempIPv6Address[16];
uint8_t ctxId;
bool new_neighbour_created;
while (data_length) {
//Read
@ -1383,8 +1378,8 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
memcpy(&tempIPv6Address[8], ptr, 8);
tr_debug("Register %s", trace_ipv6(tempIPv6Address));
//Register GP --> 16
thread_nd_address_registration(cur, tempIPv6Address, mac16, cur->mac_parameters->pan_id, mac64);
thread_extension_address_registration(cur, tempIPv6Address, mac64);
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);
} else {
tr_debug("No Context %u", ctxId);
}
@ -1403,8 +1398,8 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
}
} else {
//Register GP --> 16
thread_nd_address_registration(cur, ptr, mac16, cur->mac_parameters->pan_id, mac64);
thread_extension_address_registration(cur, ptr, mac64);
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);
}
ptr += 16;
@ -1415,14 +1410,12 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
{
(void) interface_id;
thread_leader_data_t leaderData;
mle_neigh_table_entry_t *entry_temp;
mac_neighbor_table_entry_t *entry_temp;
bool rssiTLV;
bool leaderDataReceived;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
//TLV REQUSTED
if (mle_tlv_type_requested(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length)) {
@ -1471,9 +1464,13 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
}
// parent request received
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
entry_temp->mode = (MLE_FFD_DEV | MLE_RX_ON_IDLE | MLE_THREAD_REQ_FULL_DATA_SET);
//Set MAC modes
mle_mode_parse_to_mac_entry(entry_temp, (MLE_FFD_DEV | MLE_RX_ON_IDLE));
thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index, MLE_THREAD_REQ_FULL_DATA_SET);
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index, linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
}
if(!entry_temp) {
if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
@ -1487,17 +1484,17 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
return;
}
if (mle_class_free_entry_count_get(cur->id) < 1) {
if (mle_class_free_entry_count_get(cur) < 1) {
tr_info("Drop MLE message: no space left in the MLE table");
return;
}
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && mle_class_rfd_entry_count_get(cur->id) >= THREAD_MAX_MTD_CHILDREN) {
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && mle_class_rfd_entry_count_get(cur) >= THREAD_MAX_MTD_CHILDREN) {
tr_info("Drop MLE message: maximum MTD child count reached.");
return;
}
if (!(mode & MLE_RX_ON_IDLE) && mle_class_sleepy_entry_count_get(cur->id) >= THREAD_MAX_SED_CHILDREN) {
if (!(mode & MLE_RX_ON_IDLE) && mle_class_sleepy_entry_count_get(cur) >= THREAD_MAX_SED_CHILDREN) {
tr_info("Drop MLE message: maximum SED child count reached.");
return;
}
@ -1571,10 +1568,14 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
return;
}
// If we are in REED mode and receive child IR request from our parent, call connection error.
// If we are in REED mode and receive child ID request from our parent, call connection error.
if (thread_am_reed(cur)) {
if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
tr_debug("Child ID req from own parent -> connection error");
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (entry_temp) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
}
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
return;
}
@ -1714,7 +1715,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
if (mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
//Correct TLV's lets response
if (!thread_is_router_addr(shortAddress)) {
if (leaderDataReceived && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) {
if (leaderDataReceived && thread_partition_match(cur, &leaderData)) {
//REED or end device send response
thread_router_accept_to_endevice(cur, mle_msg, challengeTlv.dataPtr, challengeTlv.tlvLen);
} else {
@ -1726,7 +1727,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
return;
}
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
@ -1738,9 +1739,11 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
*
*/
if (entry_temp && entry_temp->handshakeReady) {
mle_entry_timeout_refresh(entry_temp);
thread_router_synch_accept_request_build(cur, mle_msg, entry_temp->short_adr, challengeTlv.dataPtr, challengeTlv.tlvLen, requestTlv.dataPtr, requestTlv.tlvLen);
if (entry_temp && entry_temp->connected_device) {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime);
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
thread_router_synch_accept_request_build(cur, mle_msg, entry_temp->mac16, challengeTlv.dataPtr, challengeTlv.tlvLen, requestTlv.dataPtr, requestTlv.tlvLen);
}
}
bool update_mac_mib = false;
@ -1759,7 +1762,7 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
}
//validate partition id
if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
if (!thread_partition_match(cur, &leaderData)) {
tr_debug("Drop link request from wrong partition");
return;
}
@ -1767,26 +1770,28 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
if (entry_temp) {
/*remove from child list when becoming router*/
// Was this previously our child? If yes, update.
if ((entry_temp->short_adr & THREAD_CHILD_MASK) && thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) {
if ((entry_temp->mac16 & THREAD_CHILD_MASK) && thread_router_addr_from_addr(entry_temp->mac16) == cur->thread_info->routerShortAddress) {
thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16);
}
update_mac_mib = true;
entry_temp->short_adr = shortAddress; // short address refreshed
entry_temp->mac16 = shortAddress; // short address refreshed
if (entry_temp->handshakeReady) {
if (entry_temp->connected_device) {
if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
if (thread_rfd_device(entry_temp->mode)) {
thread_address_registration_tlv_parse(addressRegisteredTlv.dataPtr, addressRegisteredTlv.tlvLen, cur, entry_temp->short_adr, entry_temp->mac64);
if (!entry_temp->ffd_device) {
thread_address_registration_tlv_parse(addressRegisteredTlv.dataPtr, addressRegisteredTlv.tlvLen, cur, entry_temp->mac16, entry_temp->mac64);
}
}
mle_entry_timeout_refresh(entry_temp);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime);
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
if (!mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex) && update_mac_mib) {
//GET
mlme_get_t get_req;
get_req.attr = macDeviceTable;
get_req.attr_index = entry_temp->attribute_index;
get_req.attr_index = entry_temp->index;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
}
response_type = MLE_COMMAND_ACCEPT;
@ -1853,32 +1858,41 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
createNew = thread_bootstrap_link_create_check(cur, shortAddress);
//Send Response
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, createNew, &new_entry);
if (entry_temp) {
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, new_entry);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
}
entry_temp->threadNeighbor = true;
entry_temp->short_adr = shortAddress;
mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry);
if (entry_temp->timeout_rx) {
mle_entry_timeout_refresh(entry_temp);
entry_temp->mac16 = shortAddress;
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64, entry_temp->mac16,llFrameCounter, false);
mac_helper_devicetable_set(&device_desc, cur, entry_temp->index, security_headers->KeyIndex, new_entry);
uint32_t link_lifetime;
if (new_entry) {
link_lifetime = THREAD_DEFAULT_LINK_LIFETIME;
} else {
mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
link_lifetime = entry_temp->link_lifetime;
}
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, link_lifetime);
if (thread_is_router_addr(shortAddress)) {
entry_temp->handshakeReady = 1;
entry_temp->connected_device = 1;
}
entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index, true);
thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
thread_routing_update_link_margin(cur, entry_temp->mac16, linkMargin, linkMarginfronNeigh);
//Read Source address and Challenge
mac_data_poll_protocol_poll_mode_decrement(cur);
thread_router_accept_request_build(cur, mle_msg, entry_temp->short_adr, challengeTlv.dataPtr, challengeTlv.tlvLen, MLE_COMMAND_ACCEPT, rssiTLV, linkMargin);
thread_router_accept_request_build(cur, mle_msg, entry_temp->mac16, challengeTlv.dataPtr, challengeTlv.tlvLen, MLE_COMMAND_ACCEPT, rssiTLV, linkMargin);
blacklist_update(mle_msg->packet_src_address, true);
} else {
@ -1899,11 +1913,12 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
mle_tlv_info_t addressRegisterTlv = {0};
mle_tlv_info_t challengeTlv = {0};
mle_tlv_info_t tlv_req = {0};
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status)) {
if (1 == status && thread_check_is_this_my_parent(cur, entry_temp)) {
tr_debug("parent has removed REED");
tr_debug("Parent has removed REED");
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
}
return;
@ -1923,9 +1938,10 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
}
//Keep alive updated
entry_temp->ttl = entry_temp->timeout_rx;
entry_temp->last_contact_time = protocol_core_monotonic_time;
entry_temp->mode = mode;
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
mle_mode_parse_to_mac_entry(entry_temp, mode);
thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index, mode);
addressRegisterTlv.tlvType = MLE_TYPE_UNASSIGNED;
mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisterTlv);
@ -1935,25 +1951,26 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
if (addressRegisterTlv.tlvType == MLE_TYPE_ADDRESS_REGISTRATION &&
thread_rfd_device(entry_temp->mode)) {
!entry_temp->ffd_device) {
tr_debug("Register child address");
thread_address_registration_tlv_parse(addressRegisterTlv.dataPtr, addressRegisterTlv.tlvLen, cur, entry_temp->short_adr, entry_temp->mac64);
thread_address_registration_tlv_parse(addressRegisterTlv.dataPtr, addressRegisterTlv.tlvLen, cur, entry_temp->mac16, entry_temp->mac64);
}
if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
tr_debug("Setting child timeout, value=%"PRIu32, timeout);
entry_temp->holdTime = 90;
mle_entry_timeout_update(entry_temp, timeout);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
} else {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime);
}
if (!leaderDataReceived) {
tr_debug("Child synch req");
}
tr_debug("Keep-Alive -->Respond Child");
//Response
thread_child_update_response(cur, mle_msg->packet_src_address, mode, entry_temp->short_adr, timeout, &addressRegisterTlv, &tlv_req, &challengeTlv, active_timestamp, pending_timestamp);
thread_child_update_response(cur, mle_msg->packet_src_address, mode, entry_temp->mac16, timeout, &addressRegisterTlv, &tlv_req, &challengeTlv, active_timestamp, pending_timestamp);
}
break;
@ -1969,11 +1986,16 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
case MLE_COMMAND_DATA_REQUEST: {
mle_tlv_info_t requestTlv;
tr_info("Recv Router Data Request");
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
return;
}
mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, entry_temp->mode);
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
uint8_t mode = mle_mode_write_from_mac_entry(entry_temp);
mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index);
mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode);
}
break;
default:
@ -2184,7 +2206,10 @@ void thread_router_bootstrap_child_id_reject(protocol_interface_info_entry_t *cu
while (req) {
tr_debug("Remove entry from list");
//Remove entry from list
mle_class_remove_neighbour(cur->id, req->euid64, ADDR_802_15_4_LONG);
mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), req->euid64, ADDR_802_15_4_LONG);
if (neighbor) {
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neighbor);
}
ns_dyn_mem_free(req);
req = thread_child_id_request_entry_get_from_the_list(cur);
@ -2206,7 +2231,6 @@ void thread_router_bootstrap_active_router_attach(protocol_interface_info_entry_
cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
thread_routing_activate(&cur->thread_info->routing);
thread_router_synch_new_router(cur, ADDR_LINK_LOCAL_ALL_ROUTERS);
mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
thread_bootstrap_ready(cur);
thread_bootstrap_network_prefixes_process(cur);
thread_nd_service_activate(cur->id);
@ -2226,7 +2250,7 @@ static int thread_validate_own_routeid_from_new_mask(const uint8_t *master_route
return ret_val;
}
int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, mle_neigh_table_entry_t *entry)
int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, struct mac_neighbor_table_entry *entry)
{
(void) route_len;
@ -2239,9 +2263,9 @@ int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur,
route_data = route_tlv;
uint16_t mac16 = mac_helper_mac16_address_get(cur);
if (!thread_is_router_addr(entry->short_adr)) {
if (!thread_is_router_addr(entry->mac16)) {
// Received route tlv from non router ignore
tr_info("drop route Processing from end device %x", entry->short_adr);
tr_info("drop route Processing from end device %x", entry->mac16);
return 0;
}
@ -2251,21 +2275,20 @@ int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur,
thread_routing_leader_connection_validate(cur->thread_info,routing->networkFragmentationTimer);
routing->networkFragmentationTimer = 0;
if (thread_validate_own_routeid_from_new_mask(router_id_mask, thread_router_id_from_addr(mac16)) != 0) {
tr_debug("RouterID not valid any More");
thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_KICK, NULL);
return 0;
}
}
} else if (!thread_info(cur)->thread_endnode_parent ||
thread_info(cur)->thread_endnode_parent->shortAddress != entry->short_adr ) {
thread_info(cur)->thread_endnode_parent->shortAddress != entry->mac16 ) {
return 0;
}
/* XXX Is short_src_adr ever reset? Is it undefined if info not in msg? */
/* Don't add routing link if MLE link is NOT bi-directional (i.e. we can only hear) */
if (entry->handshakeReady) {
thread_routing_add_link(cur, entry->short_adr, linkMargin, route_id_seq, router_id_mask, route_data, false);
if (entry->connected_device) {
thread_routing_add_link(cur, entry->mac16, linkMargin, route_id_seq, router_id_mask, route_data, false);
}
return 0;
@ -2342,6 +2365,13 @@ static void thread_reed_advertisements_cb(void* arg)
protocol_interface_info_entry_t *cur = arg;
cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = NULL;
if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
/* Own attach is ongoing, try to send advertisement after few seconds */
cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb, 2 * 1000, cur);
return;
}
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED &&
cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER){
thread_reed_advertise(cur);
@ -2461,23 +2491,22 @@ void thread_router_bootstrap_timer(protocol_interface_info_entry_t *cur, uint32_
return;
}
void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, mle_neigh_table_entry_t *entry_temp, uint16_t shortAddress)
void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, struct mac_neighbor_table_entry *entry_temp, uint16_t shortAddress)
{
if (entry_temp) {
entry_temp->threadNeighbor = true;
if (entry_temp->timeout_rx == 0 || thread_is_router_addr(shortAddress)) {
entry_temp->timeout_rx = THREAD_DEFAULT_LINK_LIFETIME / MLE_TIMER_TICKS_SECONDS;
entry_temp->timeout_rx++;
if (thread_is_router_addr(shortAddress)) {
entry_temp->link_lifetime = THREAD_DEFAULT_LINK_LIFETIME;
entry_temp->link_lifetime++;
}
if (thread_is_router_addr(shortAddress)) {
//Update MAC Security PIB table by get & set Operation
mlme_get_t get_req;
get_req.attr = macDeviceTable;
get_req.attr_index = entry_temp->attribute_index;
get_req.attr_index = entry_temp->index;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
entry_temp->ttl = entry_temp->timeout_rx;
entry_temp->lifetime = entry_temp->link_lifetime;
}
} else {
//
@ -2661,14 +2690,14 @@ static int thread_router_bootstrap_network_data_propagation(protocol_interface_i
static void thread_router_bootstrap_network_data_push_to_sleep_child(protocol_interface_info_entry_t *cur, bool stableDataUpdate)
{
uint8_t childLinkLocalAddress[16];
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
memcpy(childLinkLocalAddress, ADDR_LINK_LOCAL_PREFIX, 8);
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if (cur_entry->threadNeighbor) {
if (!(cur_entry->mode & MLE_RX_ON_IDLE)) {
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (!cur_entry->rx_on_idle) {
memcpy(&childLinkLocalAddress[8], cur_entry->mac64, 8);
childLinkLocalAddress[8] ^= 2;
if (cur_entry->mode & MLE_THREAD_REQ_FULL_DATA_SET) {
if (thread_neighbor_class_request_full_data_setup(&cur->thread_info->neighbor_class, cur_entry->index)) {
thread_router_bootstrap_network_data_propagation(cur, childLinkLocalAddress, true);
} else {
if (stableDataUpdate) {
@ -2678,7 +2707,6 @@ static void thread_router_bootstrap_network_data_push_to_sleep_child(protocol_in
}
}
}
}
void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -43,13 +43,14 @@ struct protocol_interface_info_entry;
struct thread_info_s;
struct mle_security_header;
struct buffer;
struct mac_neighbor_table_entry;
void thread_router_bootstrap_reed_advertisements_start(protocol_interface_info_entry_t *cur);
void thread_router_bootstrap_reed_merge_advertisement(protocol_interface_info_entry_t *cur);
int thread_router_bootstrap_mle_advertise(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur);
int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *child);
int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child);
uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur);
void thread_router_bootstrap_child_id_handler(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_child_id_reject(struct protocol_interface_info_entry *cur);
@ -61,11 +62,11 @@ int thread_router_bootstrap_link_synch_start(struct protocol_interface_info_entr
bool thread_router_bootstrap_router_downgrade(struct protocol_interface_info_entry *cur);
bool thread_router_bootstrap_reed_upgrade(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_active_router_attach(struct protocol_interface_info_entry *cur);
int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, mle_neigh_table_entry_t *entry);
int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, struct mac_neighbor_table_entry *entry);
void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, struct mle_security_header *security_headers);
void thread_router_bootstrap_timer(protocol_interface_info_entry_t *cur, uint32_t ticks);
uint32_t thread_router_bootstrap_random_upgrade_jitter();
void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, mle_neigh_table_entry_t *entry_temp, uint16_t shortAddress);
uint32_t thread_router_bootstrap_random_upgrade_jitter(void);
void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, struct mac_neighbor_table_entry *entry_temp, uint16_t shortAddress);
void thread_router_bootstrap_multicast_forwarder_enable(protocol_interface_info_entry_t *cur, buffer_t *buf);
void thread_router_bootstrap_anycast_address_register(protocol_interface_info_entry_t *cur);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -52,6 +52,7 @@
#include "6LoWPAN/Thread/thread_routing.h"
#include "6LoWPAN/Thread/thread_leader_service.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#define TRACE_GROUP "trou"
@ -183,7 +184,7 @@ static inline thread_link_quality_e thread_quality_combine(thread_link_quality_e
/* Return the quality (worse of incoming and outgoing quality) for a neighbour router */
static inline thread_link_quality_e thread_neighbour_router_quality(const thread_router_link_t *neighbour)
{
return thread_quality_combine(neighbour->incoming_quality, neighbour->outgoing_quality);
return thread_quality_combine((thread_link_quality_e) neighbour->incoming_quality, (thread_link_quality_e) neighbour->outgoing_quality);
}
@ -265,8 +266,8 @@ static int_fast8_t thread_route_fn(
uint16_t dest_router_addr = thread_router_addr_from_addr(dest);
if (dest_router_addr == mac16) {
/* We're this device's parent - transmit direct to it */
mle_neigh_table_entry_t *entry = mle_class_get_by_link_address(cur->id, dest_addr, ADDR_802_15_4_SHORT);
if (!entry || (entry->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), dest_addr, ADDR_802_15_4_SHORT);
if (!entry || !entry->ffd_device) {
/* To cover some of draft-kelsey-thread-network-data-00, we send the
* packet up to our own IP layer in the case where it's addressed to
* an unrecognised child. The special IP forwarding rules can then
@ -690,8 +691,8 @@ int_fast8_t thread_routing_add_link(protocol_interface_info_entry_t *cur,
if (our_quality_to_other_neighbour < QUALITY_10dB) {
continue;
}
thread_link_quality_e neighbours_incoming_quality_to_other_neighbour = (byte & ROUTE_DATA_IN_MASK) >> ROUTE_DATA_IN_SHIFT;
thread_link_quality_e neighbours_outgoing_quality_to_other_neighbour = (byte & ROUTE_DATA_OUT_MASK) >> ROUTE_DATA_OUT_SHIFT;
thread_link_quality_e neighbours_incoming_quality_to_other_neighbour = (thread_link_quality_e) ((byte & ROUTE_DATA_IN_MASK) >> ROUTE_DATA_IN_SHIFT);
thread_link_quality_e neighbours_outgoing_quality_to_other_neighbour = (thread_link_quality_e) ((byte & ROUTE_DATA_OUT_MASK) >> ROUTE_DATA_OUT_SHIFT);
thread_link_quality_e neighbours_quality_to_other_neighbour = thread_quality_combine(neighbours_incoming_quality_to_other_neighbour,
neighbours_outgoing_quality_to_other_neighbour);
if (neighbours_quality_to_other_neighbour < our_quality_to_other_neighbour) {
@ -975,6 +976,21 @@ static void thread_trickle_accelerate(trickle_t *t, const trickle_params_t *para
}
}
void thread_routing_trickle_advance(thread_routing_info_t *routing, uint16_t ticks)
{
trickle_t *t =&routing->mle_advert_timer;
if (!trickle_running(t, &thread_mle_advert_trickle_params)) {
return;
}
if ((t->t > t->now) && (t->t - t->now < ticks)) {
/* advance trickle elapsing time by number of ticks */
t->t = t->t + ticks - (t->t - t->now);
tr_debug("trickle advanced to %d, now %d ", t->t, t->now);
}
}
// This functions speeds up next advertisement depending on the disconnect period to leader
void thread_routing_leader_connection_validate(thread_info_t *thread, uint16_t disconnect_period)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -187,6 +187,7 @@ void thread_routing_free(thread_routing_info_t *routing);
void thread_routing_activate(thread_routing_info_t *routing);
void thread_routing_deactivate(thread_routing_info_t *routing);
bool thread_routing_timer(struct thread_info_s *thread, uint8_t ticks);
void thread_routing_trickle_advance(thread_routing_info_t *routing, uint16_t ticks);
void thread_routing_leader_connection_validate(struct thread_info_s *thread, uint16_t disconnect_period);
void thread_routing_set_mesh_callbacks(protocol_interface_info_entry_t *cur);
@ -233,6 +234,7 @@ int_fast8_t thread_routing_get_route_data(protocol_interface_info_entry_t *cur,
#define thread_routing_activate(routing)
#define thread_routing_deactivate(routing)
#define thread_routing_timer(thread, ticks) false
#define thread_routing_trickle_advance(routing, ticks)
#define thread_routing_leader_connection_validate(thread, disconnect_period)
#define thread_routing_set_mesh_callbacks(cur)
#define thread_routing_cost_get_by_router_id(routing, routerId) (0)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
@ -49,11 +49,13 @@
#include "6LoWPAN/Thread/thread_discovery.h"
#include "6LoWPAN/Thread/thread_nvm_store.h"
#include "6LoWPAN/Thread/thread_extension_bootstrap.h"
#include "6LoWPAN/Thread/thread_neighbor_class.h"
#include "MLE/mle.h"
#include "thread_meshcop_lib.h"
#include "thread_diagcop_lib.h"
#include "coap_service_api.h"
#include "Service_Libs/mle_service/mle_service_api.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h"
#define TRACE_GROUP "tapi"
@ -452,7 +454,7 @@ int thread_test_key_rotation_update(int8_t interface_id, uint32_t thrKeyRotation
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
if (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) {
linkConfiguration->key_rotation = thrKeyRotation;
thread_calculate_key_guard_timer(cur, linkConfiguration, false);
thread_key_guard_timer_calculate(cur, linkConfiguration, false);
ret_val = 0;
}
}
@ -593,7 +595,7 @@ int thread_test_security_material_set(int8_t interface_id, bool enableSecurity,
mle_service_security_set_security_key(cur->id, key_material, key_index, true);
//Gen also Next Key
thread_security_next_key_generate(cur, linkConfiguration->master_key, thrKeySequenceCounter);
thread_calculate_key_guard_timer(cur, linkConfiguration, false);
thread_key_guard_timer_calculate(cur, linkConfiguration, false);
}
} else {
ret_val = 0;
@ -625,7 +627,8 @@ int thread_test_version_set(int8_t interface_id, uint8_t version)
thread_version = version;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return -1;
/*We already stored the new Thread version above, so even if cur is NULL the version is updated.*/
return 0;
}
cur->thread_info->version = version;
return 0;
@ -1114,22 +1117,22 @@ int8_t thread_test_child_info_get(int8_t interface_id, uint8_t index, uint16_t *
protocol_interface_info_entry_t *cur;
uint8_t n= 0;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->thread_info || cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) {
if (!cur || !cur->mac_parameters || !cur->thread_info || cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) {
return -1;
}
uint16_t mac16 = mac_helper_mac16_address_get(cur);
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(interface_id);
if (!mle_table) {
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
if (!mac_table_list) {
return -1;
}
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if (cur_entry->threadNeighbor && thread_router_addr_from_addr(cur_entry->short_adr) == thread_router_addr_from_addr(mac16)) {
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (thread_router_addr_from_addr(cur_entry->mac16) == thread_router_addr_from_addr(mac16)) {
if (n == index) {
*short_addr = cur_entry->short_adr;
*short_addr = cur_entry->mac16;
memcpy(mac64,cur_entry->mac64, 8);
*sleepy = (cur_entry->mode & MLE_RX_ON_IDLE) != MLE_RX_ON_IDLE;
*margin = cur_entry->link_margin;
*sleepy = cur_entry->rx_on_idle != true;
*margin = thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, cur_entry->index);
return 0;
}
n++;
@ -1156,17 +1159,17 @@ int8_t thread_test_neighbour_info_get(int8_t interface_id, uint8_t index, uint16
return -1;
}
uint16_t mac16 = mac_helper_mac16_address_get(cur);
mle_neigh_table_list_t *mle_table = mle_class_active_list_get(interface_id);
if (!mle_table) {
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
if (!mac_table_list) {
return -1;
}
ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
if (cur_entry->threadNeighbor && thread_router_addr_from_addr(cur_entry->short_adr) != thread_router_addr_from_addr(mac16)) {
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (thread_router_addr_from_addr(cur_entry->mac16) != thread_router_addr_from_addr(mac16)) {
if (n == index) {
*short_addr = cur_entry->short_adr;
*short_addr = cur_entry->mac16;
memcpy(mac64,cur_entry->mac64, 8);
*margin = cur_entry->link_margin;
*margin = thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, cur_entry->index);
return 0;
}
n++;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -35,6 +35,7 @@
#include "NWK_INTERFACE/Include/protocol_timer.h"
#include "Service_Libs/etx/etx.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mpx_api.h"
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
#include "lowpan_adaptation_interface.h"
@ -42,9 +43,15 @@
#ifdef HAVE_RPL
#include "RPL/rpl_data.h"
#endif
#include "6LoWPAN/ws/ws_common.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/ws/ws_common.h"
#define TRACE_GROUP "6lAd"
typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm);
// #define EXTRA_DEBUG_EXTRA
#ifdef EXTRA_DEBUG_EXTRA
#define tr_debug_extra(...) tr_debug(__VA_ARGS__)
@ -88,6 +95,9 @@ typedef struct {
uint16_t max_indirect_big_packets_total;
uint16_t max_indirect_small_packets_per_child;
bool fragmenter_active; /*!< Fragmenter state */
adaptation_etx_update_cb *etx_update_cb;
mpx_api_t *mpx_api;
uint16_t mpx_user_id;
ns_list_link_t link; /*!< List link entry */
} fragmenter_interface_t;
@ -101,8 +111,8 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur);
/* Data direction and message length validation */
static bool lowpan_adaptation_indirect_data_request(mle_neigh_table_entry_t *mle_entry);
static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf);
static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *mle_entry);
static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_interface_t *interface_ptr);
/* Common data tx request process functions */
static void lowpan_active_buffer_state_reset(fragmenter_tx_entry_t *tx_buffer);
@ -110,7 +120,7 @@ static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *int
static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size);
static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast);
static void lowpan_adaptation_data_request_primitiv_set(const buffer_t *buf, mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur);
static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr);
static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr, fragmenter_interface_t *interface_ptr);
/* Tx confirmation local functions */
static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf);
@ -120,12 +130,49 @@ static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status);
static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr);
/* Fragmentation local functions */
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur);
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr);
static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq);
static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm)
{
switch (confirm->status) {
case MLME_TX_NO_ACK:
case MLME_NO_DATA:
case MLME_SUCCESS:
if (buf->link_specific.ieee802_15_4.requestAck) {
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
bool success = false;
if (confirm->status == MLME_SUCCESS) {
success = true;
}
// Gets table entry
mac_neighbor_table_entry_t *neigh_table_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + PAN_ID_LEN, buf->dst_sa.addr_type);
if (neigh_table_ptr) {
etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries , success, neigh_table_ptr->index);
// Updates ETX statistics
etx_storage_t * etx_entry = etx_storage_entry_get(cur->id, neigh_table_ptr->index);
if (etx_entry) {
if (neigh_table_ptr->link_role == PRIORITY_PARENT_NEIGHBOUR) {
protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4);
} else if (neigh_table_ptr->link_role == SECONDARY_PARENT_NEIGHBOUR) {
protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
}
}
}
}
}
break;
default:
break;
}
}
//Discover
static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId)
{
@ -139,6 +186,18 @@ static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t inter
return NULL;
}
static struct protocol_interface_info_entry *lowpan_adaptation_network_interface_discover(const mpx_api_t* api)
{
ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) {
if (api == interface_ptr->mpx_api) {
return protocol_stack_interface_info_get_by_id(interface_ptr->interface_id);
}
}
return NULL;
}
static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr , buffer_t *buf)
{
@ -164,7 +223,7 @@ static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interf
* Data confirm has freed the corresponding "active buffer" and this function will look for new buffer to be set as active buffer.
*/
ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) {
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf);
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
//Check that we not trig second active fragmentation process
if (fragmented_needed && interface_ptr->fragmenter_active) {
tr_debug("Do not trig Second active fragmentation");
@ -179,9 +238,13 @@ static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interf
//fragmentation needed
static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf)
static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_interface_t *interface_ptr)
{
uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf);
uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf);
if (interface_ptr->mpx_api) {
overhead += interface_ptr->mpx_api->mpx_headroom_size_get(interface_ptr->mpx_api, interface_ptr->mpx_user_id);
}
if (buffer_data_length(buf) > (int16_t)mac_helper_max_payload_size(cur, overhead)) {
@ -191,9 +254,9 @@ static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_en
}
}
static bool lowpan_adaptation_indirect_data_request(mle_neigh_table_entry_t *mle_entry)
static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *entry_ptr)
{
if (mle_entry && !(mle_entry->mode & MLE_RX_ON_IDLE)) {
if (entry_ptr && !(entry_ptr->rx_on_idle)) {
return true;
}
return false;
@ -302,6 +365,14 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si
return 0;
}
void lowpan_adaptation_interface_etx_update_enable(int8_t interface_id)
{
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
if (interface_ptr) {
interface_ptr->etx_update_cb = lowpan_adaptation_etx_update_cb;
}
}
int8_t lowpan_adaptation_interface_free(int8_t interface_id)
{
//Discover
@ -350,6 +421,44 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
return 0;
}
static void lowpan_adaptation_mpx_data_confirm(const mpx_api_t* api, const struct mcps_data_conf_s *data)
{
protocol_interface_info_entry_t * interface = lowpan_adaptation_network_interface_discover(api);
lowpan_adaptation_interface_tx_confirm(interface, data);
}
static void lowpan_adaptation_mpx_data_indication(const mpx_api_t* api, const struct mcps_data_ind_s *data)
{
protocol_interface_info_entry_t * interface = lowpan_adaptation_network_interface_discover(api);
lowpan_adaptation_interface_data_ind(interface, data);
}
int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_api_s *mpx_api, uint16_t mpx_user_id)
{
//Discover
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
if (!interface_ptr) {
return -1;
}
if (!mpx_api && interface_ptr->mpx_api) {
//Disable Data Callbacks from MPX Class
interface_ptr->mpx_api->mpx_user_registration(interface_ptr->mpx_api, NULL, NULL, interface_ptr->mpx_user_id);
}
interface_ptr->mpx_api = mpx_api;
interface_ptr->mpx_user_id = mpx_user_id;
if (interface_ptr->mpx_api) {
//Register MPX callbacks: confirmation and indication
interface_ptr->mpx_api->mpx_user_registration(interface_ptr->mpx_api, lowpan_adaptation_mpx_data_confirm, lowpan_adaptation_mpx_data_indication, interface_ptr->mpx_user_id);
}
return 0;
}
static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size)
{
@ -377,7 +486,7 @@ static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_b
return indirec_entry;
}
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur)
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr)
{
uint8_t *ptr;
uint16_t uncompressed_size;
@ -405,7 +514,11 @@ static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_ent
frag_entry->orig_size = frag_entry->size;
frag_entry->size += (uncompressed_size - frag_entry->pattern);
uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf);
uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf);
if (interface_ptr->mpx_api) {
overhead += interface_ptr->mpx_api->mpx_headroom_size_get(interface_ptr->mpx_api, interface_ptr->mpx_user_id);
}
frag_entry->frag_max = mac_helper_max_payload_size(cur, overhead);
@ -498,24 +611,25 @@ static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_inte
buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_entry_t *cur, buffer_t *buf)
{
mac_neighbor_table_entry_t *neigh_entry_ptr = NULL;
//Validate is link known and set indirect, datareq and security key id mode
if (buf->dst_sa.addr_type == ADDR_NONE) {
goto tx_error_handler;
}
mle_neigh_table_entry_t *mle_entry = NULL;
/* If MLE is enabled, we will talk if we have an MLE association */
if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG ) {
mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa.address + 2, buf->dst_sa.addr_type);
neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type);
} else if(buf->dst_sa.addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa.address + 2)) != 0xffff) {
mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa.address + 2, buf->dst_sa.addr_type);
neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type);
}
//Validate neighbour
if (!buf->options.ll_security_bypass_tx && mle_entry) {
if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) {
if (mle_entry->handshakeReady || mle_entry->thread_commission) {
if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device) {
} else {
//tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true));
@ -534,14 +648,14 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_
buf->link_specific.ieee802_15_4.requestAck = false;
} else {
buf->link_specific.ieee802_15_4.requestAck = true;
buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(mle_entry);
buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr);
}
if (buf->link_specific.ieee802_15_4.key_id_mode != B_SECURITY_KEY_ID_2) {
if (!buf->link_specific.ieee802_15_4.requestAck ) {
buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT;
} else if (mle_entry && !mle_entry->thread_commission) {
} else if (ws_info(cur) || (neigh_entry_ptr && !neigh_entry_ptr->trusted_device)) {
buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT;
} else {
buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_IMPLICIT;
@ -551,6 +665,11 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_
return buf;
tx_error_handler:
if (neigh_entry_ptr && neigh_entry_ptr->nud_active) {
mac_neighbor_info(cur)->active_nud_process--;
neigh_entry_ptr->nud_active = false;
}
socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL);
return NULL;
@ -616,7 +735,7 @@ static bool lowpan_adaptation_indirect_cache_sanity_check(protocol_interface_inf
// entry is in cache and is not sent to mac => trigger this
tr_debug_extra("sanity check, push seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address));
fragmenter_tx_entry->indirect_data_cached = false;
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry);
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr);
return true;
}
}
@ -638,7 +757,7 @@ static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_ent
if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) {
tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address));
fragmenter_tx_entry->indirect_data_cached = false;
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry);
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr);
return true;
}
}
@ -674,7 +793,7 @@ static fragmenter_tx_entry_t* lowpan_adaptation_indirect_first_cached_request_ge
return NULL;
}
static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mle_neigh_table_entry_t *neighbour_to_count)
static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mac_neighbor_table_entry_t *neighbour_to_count)
{
if (interface_ptr->max_indirect_small_packets_per_child == 0) {
return;
@ -683,7 +802,7 @@ static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info
uint_fast16_t count = 0;
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) {
mle_neigh_table_entry_t *tx_neighbour = mle_class_get_by_link_address(cur->id, tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type);
mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type);
if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) {
if (++count >= interface_ptr->max_indirect_small_packets_per_child) {
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry);
@ -710,7 +829,7 @@ static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface
}
}
static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr)
static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr, fragmenter_interface_t *interface_ptr)
{
mcps_data_req_t dataReq;
@ -737,8 +856,12 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
}
}
if (interface_ptr->mpx_api) {
interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id);
} else {
cur->mac_api->mcps_data_req(cur->mac_api, &dataReq);
}
}
int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf)
{
@ -756,7 +879,7 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
}
//Check packet size
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf);
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
bool is_unicast = buf->link_specific.ieee802_15_4.requestAck;
bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess;
if (!indirect) {
@ -783,7 +906,7 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
if (fragmented_needed) {
//Fragmentation init
if (lowpan_message_fragmentation_init(buf, tx_ptr, cur) ) {
if (lowpan_message_fragmentation_init(buf, tx_ptr, cur, interface_ptr) ) {
tr_error("Fragment init fail");
if (indirect) {
ns_dyn_mem_free(tx_ptr->fragmenter_buf);
@ -801,9 +924,9 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
if (indirect) {
//Add to indirectQUue
fragmenter_tx_entry_t *tx_ptr_cached;
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa.address + 2, buf->dst_sa.addr_type);
if (mle_entry) {
buf->link_specific.ieee802_15_4.indirectTTL = (uint32_t) mle_entry->timeout_rx * MLE_TIMER_TICKS_MS;
mac_neighbor_table_entry_t *neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + PAN_ID_LEN, buf->dst_sa.addr_type);
if (neigh_entry_ptr) {
buf->link_specific.ieee802_15_4.indirectTTL = (uint32_t) neigh_entry_ptr->link_lifetime * 1000;
} else {
buf->link_specific.ieee802_15_4.indirectTTL = cur->mac_parameters->mac_in_direct_entry_timeout;
}
@ -812,7 +935,7 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
// Make room for new message if needed */
if (buffer_data_length(buf) <= interface_ptr->indirect_big_packet_threshold) {
lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, mle_entry);
lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, neigh_entry_ptr);
} else {
lowpan_adaptation_make_room_for_big_packet(cur, interface_ptr);
}
@ -841,7 +964,7 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
}
}
lowpan_data_request_to_mac(cur, buf, tx_ptr);
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
return 0;
@ -952,28 +1075,15 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
{
buf->link_specific.ieee802_15_4.indirectTTL -= 7000;
//Push Back to MAC
lowpan_data_request_to_mac(cur, buf, tx_ptr);
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
return 0;
}
}
switch (confirm->status) {
case MLME_TX_NO_ACK:
case MLME_NO_DATA:
case MLME_SUCCESS:
if (buf->link_specific.ieee802_15_4.requestAck) {
bool success = false;
if (confirm->status == MLME_SUCCESS) {
success = true;
if (interface_ptr->etx_update_cb) {
interface_ptr->etx_update_cb(cur, buf, confirm);
}
etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries , success, buf->dst_sa.addr_type, buf->dst_sa.address);
}
break;
default:
break;
}
//Switch original channel back
if (buf->link_specific.ieee802_15_4.rf_channel_switch) {
mac_helper_mac_channel_set(cur, buf->link_specific.ieee802_15_4.selected_channel);
@ -983,7 +1093,7 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
switch (confirm->status) {
case MLME_BUSY_CHAN:
lowpan_data_request_to_mac(cur, buf, tx_ptr);
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
break;
case MLME_SUCCESS:
@ -1005,7 +1115,7 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
return 0;
}
} else {
lowpan_data_request_to_mac(cur, buf, tx_ptr);
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
}
break;
@ -1049,6 +1159,73 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
}
static bool mac_data_is_broadcast_addr(const sockaddr_t *addr)
{
return (addr->addr_type == ADDR_802_15_4_SHORT) &&
(addr->address[2] == 0xFF && addr->address[3] == 0xFF);
}
static bool mcps_data_indication_neighbor_validate(protocol_interface_info_entry_t *cur, const sockaddr_t *addr)
{
if (thread_info(cur) || ws_info(cur) || (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE)) {
mac_neighbor_table_entry_t * neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr->address + 2, addr->addr_type);
if (neighbor && (neighbor->connected_device || neighbor->trusted_device)) {
return true;
}
/* Otherwise, we don't know them */
return false;
} else {
//6lowpan without MLE don't can't do validation
return true;
}
}
void lowpan_adaptation_interface_data_ind(protocol_interface_info_entry_t *cur, const mcps_data_ind_t *data_ind)
{
buffer_t *buf = buffer_get(data_ind->msduLength);
if (!buf || !cur) {
return;
}
uint8_t *ptr;
buffer_data_add(buf, data_ind->msdu_ptr, data_ind->msduLength);
//tr_debug("MAC Paylod size %u %s",data_ind->msduLength, trace_array(data_ind->msdu_ptr, 8));
buf->options.lqi = data_ind->mpduLinkQuality;
buf->options.dbm = data_ind->signal_dbm;
buf->src_sa.addr_type = (addrtype_t)data_ind->SrcAddrMode;
ptr = common_write_16_bit(data_ind->SrcPANId, buf->src_sa.address);
memcpy(ptr, data_ind->SrcAddr, 8);
buf->dst_sa.addr_type = (addrtype_t)data_ind->DstAddrMode;
ptr = common_write_16_bit(data_ind->DstPANId, buf->dst_sa.address);
memcpy(ptr, data_ind->DstAddr, 8);
//Set Link spesific stuff to seperately
buf->link_specific.ieee802_15_4.srcPanId = data_ind->SrcPANId;
buf->link_specific.ieee802_15_4.dstPanId = data_ind->DstPANId;
if (mac_data_is_broadcast_addr(&buf->dst_sa)) {
buf->options.ll_broadcast_rx = true;
}
buf->interface = cur;
if (data_ind->Key.SecurityLevel) {
buf->link_specific.ieee802_15_4.fc_security = true;
if (cur->mac_security_key_usage_update_cb) {
cur->mac_security_key_usage_update_cb(cur, &data_ind->Key);
}
} else {
buf->link_specific.ieee802_15_4.fc_security = false;
if (mac_helper_default_security_level_get(cur) ||
!mcps_data_indication_neighbor_validate(cur, &buf->src_sa)) {
//SET By Pass
buf->options.ll_security_bypass_rx = true;
}
}
buf->info = (buffer_info_t)(B_TO_IPV6_TXRX | B_FROM_MAC | B_DIR_UP);
protocol_push(buf);
}
static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status)
{
uint8_t socket_event;
@ -1104,22 +1281,38 @@ static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *addres
return true;
}
static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, uint8_t msduhandle)
static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle)
{
mcps_purge_t purge_req;
purge_req.msduHandle = msduhandle;
if (interface_ptr->mpx_api) {
interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id);
} else {
if (cur->mac_api->mcps_purge_req) {
cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req);
}
}
}
static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr)
{
tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq);
if (cur->mac_api->mcps_purge_req) {
lowpan_adaptation_purge_from_mac(cur, tx_ptr->buf->seq);
}
lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq);
lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL);
}
void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr)
{
//Free firts by defined short address
if (entry_ptr->mac16 < 0xfffe) {
uint8_t temp_address[2];
common_write_16_bit(entry_ptr->mac16, temp_address);
lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, temp_address, ADDR_802_15_4_SHORT);
}
lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, entry_ptr->mac64, ADDR_802_15_4_LONG);
}
int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type)
{
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,13 +21,21 @@
struct protocol_interface_info_entry;
struct mcps_data_conf_s;
struct mcps_data_ind_s;
struct buffer;
struct mpx_api_s;
struct mac_neighbor_table_entry;
int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_size);
void lowpan_adaptation_interface_etx_update_enable(int8_t interface_id);
int8_t lowpan_adaptation_interface_free(int8_t interface_id);
int8_t lowpan_adaptation_interface_reset(int8_t interface_id);
int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_api_s *mpx_api, uint16_t mpx_user_id);
/**
* \brief call this before normatl TX. This function prepare buffer link spesific metadata and verify packet destination
*/
@ -37,10 +45,14 @@ int8_t lowpan_adaptation_interface_tx(struct protocol_interface_info_entry *cur,
int8_t lowpan_adaptation_interface_tx_confirm(struct protocol_interface_info_entry *cur, const struct mcps_data_conf_s *confirm);
void lowpan_adaptation_interface_data_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data_ind);
struct buffer *lowpan_adaptation_reassembly(struct protocol_interface_info_entry *cur, struct buffer *buf);
bool lowpan_adaptation_tx_active(int8_t interface_id);
void lowpan_adaptation_remove_free_indirect_table(struct protocol_interface_info_entry *cur_interface, struct mac_neighbor_table_entry *entry_ptr);
int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type);
int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child);

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WS_BOOTSTRAP_H_
#define WS_BOOTSTRAP_H_
typedef enum {
WS_INIT_EVENT = 0, /**< tasklet initializion event*/
WS_DISCOVERY_START, /**< discovery start*/
WS_CONFIGURATION_START, /**< configuration learn start*/
WS_AUTHENTICATION_START, /**< authentication start*/
WS_OPERATION_START, /**< active operation start*/
WS_ROUTING_READY, /**< RPL routing connected to BR*/
WS_ADDRESS_ADDED /**< Address added to IF*/
} ws_bootsrap_event_type_e;
#ifdef HAVE_WS
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur);
/*State machine transactions*/
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_configuration_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_authentication_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_operation_start(protocol_interface_info_entry_t *cur);
void ws_bootstrap_event_routing_ready(protocol_interface_info_entry_t *cur);
void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *cur);
void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
void ws_bootstrap_trigle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
#else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
#define ws_bootstrap_state_machine(cur)
#endif //HAVE_WS
#endif /* WS_BOOTSTRAP_H_ */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WS_COMMON_H_
#define WS_COMMON_H_
#include "ns_types.h"
#include "fhss_api.h"
#include "fhss_config.h"
#include "net_fhss.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_neighbor_class.h"
struct ws_pan_information_s;
struct ws_neighbor_class_s;
typedef struct parent_info_s {
uint16_t pan_id; /**< PAN ID */
uint8_t addr[8]; /**< address */
uint8_t link_quality; /**< LQI value measured during reception of the MPDU */
int8_t signal_dbm; /**< This extension for normal IEEE 802.15.4 Data indication */
ws_pan_information_t pan_information;
ws_utt_ie_t ws_utt;
ws_us_ie_t ws_us;
uint32_t timestamp; /**< Timestamp when packet was received */
}parent_info_t;
typedef struct ws_info_s {
char network_name[33]; // Network name max 32 octets + terminating 0.
uint16_t network_pan_id;
trickle_t trickle_pan_config_solicit;
trickle_t trickle_pan_config;
trickle_t trickle_pan_advertisement_solicit;
trickle_t trickle_pan_advertisement;
uint8_t rpl_state; // state from rpl_event_t
uint8_t pas_requests; // Amount of PAN solicits sent
parent_info_t parent_info;
uint32_t pan_version_timer; /**< border router version udate timeout */
uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */
uint8_t gtkhash[32];
bool configuration_learned:1;
struct ws_pan_information_s pan_information;
ws_hopping_schedule_t hopping_schdule;
struct ws_neighbor_class_s neighbor_storage;
struct fhss_timer *fhss_timer_ptr; // Platform adaptation for FHSS timers.
struct fhss_api *fhss_api;
} ws_info_t;
#ifdef HAVE_WS
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur);
int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur);
void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
#define ws_info(cur) ((cur)->ws_info)
#else
#define ws_info(cur) ((ws_info_t *) NULL)
#define ws_common_seconds_timer(cur, seconds)
#define ws_common_neighbor_update(cur, ll_address) ((void) 0)
#define ws_common_fast_timer(cur, ticks) ((void) 0)
#endif //HAVE_WS
#endif //WS_COMMON_H_

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WS_COMMON_DEFINES_H_
#define WS_COMMON_DEFINES_H_
#define WH_IE_ELEMENT_HEADER_LENGTH 3
/* Header IE Sub elements */
#define WH_IE_UTT_TYPE 1 /**< Unicast Timing and Frame type information */
#define WH_IE_BT_TYPE 2 /**< Broadcast timing information */
#define WH_IE_FC_TYPE 3 /**< Flow Control for Extended Direct Frame Exchange */
#define WH_IE_RSL_TYPE 4 /**< Received Signal Level information */
#define WH_IE_MHDS_TYPE 5 /**< MHDS information for mesh routing */
#define WH_IE_VH_TYPE 6 /**< Vendor header information */
#define WS_WP_NESTED_IE 4 /**< WS nested Payload IE element'selement could include mltiple sub payload IE */
#define WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH 2
/* Payload IE sub elements in side WS_WP_NESTED_IE */
#define WP_PAYLOAD_IE_US_TYPE 1 /**< Unicast Schedule information */
#define WP_PAYLOAD_IE_BS_TYPE 2 /**< Broadcast Schedule information */
#define WP_PAYLOAD_IE_VP_TYPE 3 /**< Vendor Payload information */
#define WP_PAYLOAD_IE_PAN_TYPE 4 /**< PAN Information */
#define WP_PAYLOAD_IE_NETNAME_TYPE 5 /**< Network Name information */
#define WP_PAYLOAD_IE_PAN_VER_TYPE 6 /**< Pan configuration version */
#define WP_PAYLOAD_IE_GTKHASH_TYPE 7 /**< GTK Hash information */
/* WS frame types to WH_IE_UTT_TYPE */
#define WS_FT_PAN_ADVERT 0 /**< PAN Advert */
#define WS_FT_PAN_ADVERT_SOL 1 /**< PAN Advert Solicit */
#define WS_FT_PAN_CONF 2 /**< PAN Config */
#define WS_FT_PAN_CONF_SOL 3 /**< PAN Config Solicit */
#define WS_FT_DATA 4 /**< data type inside MPX */
#define WS_FT_ACK 5 /**< Enhanced ACK */
#define WS_FT_EAPOL 6 /**< EAPOL message inside MPX */
/**
* @brief ws_pan_information_t PAN information
*/
typedef struct ws_pan_information_s {
uint16_t pan_size; /**< Number devices connected to Border Router. */
uint16_t routing_cost; /**< ETX to border Router. */
uint16_t pan_version; /**< Pan configuration version will be updatd by Border router at PAN. */
bool use_parent_bs:1; /**< 1 for force to follow parent broadcast schedule. 0 node may define own schedule. */
bool rpl_routing_method:1; /**< 1 when RPL routing is selected and 0 when L2 routing. */
unsigned version:3; /**< Pan version support. */
} ws_pan_information_t;
/**
* @brief ws_hopping_schedule_t Chanel hopping schedule information
*/
typedef struct ws_hopping_schedule_s {
uint8_t fhss_uc_dwell_interval;
uint8_t fhss_bc_dwell_interval;
uint8_t regulatory_domain; /**< PHY regulatory domain default to "KR" 0x09 */
uint8_t operating_class; /**< PHY operating class default to 1 */
uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */
uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */
uint8_t channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */
uint8_t channel_spacing; /**< derived from regulatory domain. 0:200k, 1:400k, 2:600k, 3:100k */
uint8_t number_of_channels; /**< derived from regulatory domain */
uint8_t clock_drift;
uint8_t timing_accurancy;
uint16_t fixed_channel;
uint16_t fhss_bsi;
uint32_t fhss_broadcast_interval;
uint32_t channel_mask[8];
uint_fast24_t ch0_freq; // Default should be derived from regulatory domain
} ws_hopping_schedule_t;
/**
* @brief ws_utt_ie_t WS UTT-IE
*/
typedef struct ws_utt_ie {
uint8_t message_type;
uint_fast24_t ufsi;
} ws_utt_ie_t;
/**
* @brief ws_bt_ie_t WS BT-IE read
*/
typedef struct ws_bt_ie {
uint16_t broadcast_slot_number;
uint_fast24_t broadcast_interval_offset;
} ws_bt_ie_t;
/**
* @brief ws_channel_plan_zero_t WS channel plan 0 define domain and class
*/
typedef struct ws_channel_plan_zero {
uint8_t regulator_domain;
uint8_t operation_class;
} ws_channel_plan_zero_t;
/**
* @brief ws_channel_plan_one_t WS channel plan 1 define ch0, spasing and channel count
*/
typedef struct ws_channel_plan_one {
uint_fast24_t ch0;
unsigned channel_spacing:4;
uint16_t number_of_channel;
} ws_channel_plan_one_t;
/**
* @brief ws_channel_function_zero_t WS function 0 fixed channel
*/
typedef struct ws_channel_function_zero {
uint16_t fixed_channel;
} ws_channel_function_zero_t;
/**
* @brief ws_channel_function_three_t WS function 3 vendor spesific channel hop
*/
typedef struct ws_channel_function_three {
uint8_t channel_hop_count;
uint8_t *channel_list;
} ws_channel_function_three_t;
/**
* @brief ws_us_ie_t WS US-IE read
*/
typedef struct ws_us_ie {
uint8_t dwell_interval;
uint8_t clock_drift;
uint8_t timing_accurancy;
unsigned channel_plan:3;
unsigned channel_function:3;
unsigned excluded_channel_ctrl:2;
union {
ws_channel_plan_zero_t zero;
ws_channel_plan_one_t one;
} plan;
union {
ws_channel_function_zero_t zero;
ws_channel_function_three_t three;
} function;
} ws_us_ie_t;
/**
* @brief ws_bs_ie_t WS BS-IE read
*/
typedef struct ws_bs_ie {
uint32_t broadcast_interval;
uint16_t broadcast_schedule_identifier;
uint8_t dwell_interval;
uint8_t clock_drift;
uint8_t timing_accurancy;
unsigned channel_plan:3;
unsigned channel_function:3;
unsigned excluded_channel_ctrl:2;
union {
ws_channel_plan_zero_t zero;
ws_channel_plan_one_t one;
} plan;
union {
ws_channel_function_zero_t zero;
ws_channel_function_three_t three;
} function;
} ws_bs_ie_t;
#define MPX_KEY_MANAGEMENT_ENC_USER_ID 0x0001 /**< MPX Key management user ID */
#define MPX_LOWPAN_ENC_USER_ID 0xA0ED /**< MPX Lowpan User Id */
#define WS_FAN_VERSION_1_0 1
#define WS_NEIGHBOR_LINK_TIMEOUT 240
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
/*
* Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set
*/
#define CAND_PARENT_THRESHOLD 10
/*
* Hysteresis factor to be applied to CAND_PARENT_THRESHOLD when admitting or dropping nodes from the candidate parent set.
*/
#define CAND_PARENT_HYSTERISIS 3
/*
* value when send the first RPL DIS in 100ms ticks. Value is randomized between timeout/2 - timeout
*/
#define WS_RPL_DIS_INITIAL_TIMEOUT 600
/*
* value when send subsequent RPL DIS in 100 ms tics. Value is randomized between timeout/2 - timeout
*/
#define WS_RPL_DIS_TIMEOUT 1800
#endif /* WS_COMMON_DEFINES_H_ */

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WS_NEIGHBOR_CLASS_H_
#define WS_NEIGHBOR_CLASS_H_
#include "fhss_ws_extension.h"
#include "6LoWPAN/ws/ws_common_defines.h"
typedef struct ws_neighbor_class_entry {
fhss_ws_neighbor_timing_info_t fhss_data;
uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/
uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/
bool candidate_parent:1;
} ws_neighbor_class_entry_t;
/**
* Neighbor hopping info data base
*/
typedef struct ws_neighbor_class_s {
ws_neighbor_class_entry_t *neigh_info_list; /*!< Allocated hopping info array*/
uint8_t list_size; /*!< List size*/
} ws_neighbor_class_t;
/**
* ws_neighbor_class_alloc a function for allocate giving list size
*
* \param class_data pointer to structure which will be initialized by this function
* \param list_size define list size
*
* \return true Allocate Ok
* \return false Allocate Fail
*
*/
bool ws_neighbor_class_alloc(ws_neighbor_class_t *class_data, uint8_t list_size);
/**
* ws_neighbor_class_dealloc a function for free allocated neighbor hopping info
*
* \param class_data pointer to structure which will be initialized by this function
*
*/
void ws_neighbor_class_dealloc(ws_neighbor_class_t *class_data);
/**
* ws_neighbor_class_entry_t a function for search hopping info for giving neighbor attribut
*
* \param class_data pointer to structure which will be initialized by this function
* \param attribute_index define pointer to storage info
*
* \return NULL when Attribute is not correct
* \return Pointer to neighbor hopping info
*
*/
ws_neighbor_class_entry_t * ws_neighbor_class_entry_get(ws_neighbor_class_t *class_data, uint8_t attribute_index);
/**
* ws_neighbor_class_entry_t a function for search hopping info for giving neighbor attribute index
*
* \param class_data pointer to structure which will be initialized by this function
* \param entry which attribute index is counted.
*
* \return Attribute index of entry
*
*/
uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry);
/**
* ws_neighbor_class_entry_remove a function for clean information should be call when neighbor is removed
*
* \param class_data pointer to structure which will be initialized by this function
* \param attribute_index define pointer to storage info
*
*/
void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t attribute_index);
/**
* ws_neighbor_class_neighbor_unicast_time_info_update a function for update neighbor unicast time information
*
* \param ws_neighbor pointer to neighbor
* \param ws_utt Unicast time IE data
* \param timestamp timestamp for received data
*
*/
void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp);
/**
* ws_neighbor_class_neighbor_unicast_schedule_set a function for update neighbor unicast shedule information
*
* \param ws_neighbor pointer to neighbor
* \param ws_us Unicast schedule IE data
*
*/
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us);
/**
* ws_neighbor_class_neighbor_broadcast_time_info_update a function for update neighbor broadcast time information
*
* \param ws_neighbor pointer to neighbor
* \param ws_bt_ie Broadcast time IE data
* \param timestamp timestamp for received data
*
*/
void ws_neighbor_class_neighbor_broadcast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_bt_ie_t *ws_bt_ie, uint32_t timestamp);
/**
* ws_neighbor_class_neighbor_broadcast_schedule_set a function for update neighbor broadcast shedule information
*
* \param ws_neighbor pointer to neighbor
* \param ws_bs_ie Broadcast schedule IE data
*
*/
void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_bs_ie_t *ws_bs_ie);
/**
* ws_neighbor_class_rssi_from_dbm_calculate
*
* Calculates rssi value from dbm heard taking into account min sensitivity of radio
* dynamically adjusts min sensitivity if value is not properly set
*
* \param dbm_heard; dbm heard from the neighbour
*
*/
uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard);
/** Helper macros to read RSL values from neighbour class.
*
*/
#define ws_neighbor_class_rsl_in_get(ws_neighbour) (ws_neighbour->rsl_in >> WS_RSL_SCALING)
#define ws_neighbor_class_rsl_out_get(ws_neighbour) (ws_neighbour->rsl_in >> WS_RSL_SCALING)
/**
* ws_neighbor_class_neighbor_broadcast_schedule_set a function for update neighbor broadcast shedule information
*
* \param ws_neighbor pointer to neighbor
* \param dbm_heard; dbm heard from the neighbour
*
*/
void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard);
/**
* ws_neighbor_class_neighbor_broadcast_schedule_set a function for update neighbor broadcast shedule information
*
* \param ws_neighbor pointer to neighbor
* \param rsl_reported; rsl value reported by neighbour in packet from RSL-IE
*
*/
void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported);
#endif /* WS_NEIGHBOR_CLASS_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2017, Arm Limited and affiliates.
* Copyright (c) 2012-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -506,9 +506,8 @@ void border_router_start(protocol_interface_info_entry_t *cur, bool warm_link_re
if (warm_link_restart) {
return;
}
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
#ifndef NO_MLE
mle_class_list_clean(cur->id);
blacklist_clear();
#endif
@ -708,8 +707,8 @@ static int8_t arm_border_router_interface_down(protocol_interface_info_entry_t *
cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, true);
}
cur->if_lowpan_security_params->mle_security_frame_counter = mle_service_security_get_frame_counter(cur->id);
mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(cur));
#ifndef NO_MLE
mle_class_list_clean(cur->id);
blacklist_clear();
#endif
if (nd_nwk) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,8 +20,8 @@
#include "ns_trace.h"
#include "randLIB.h"
#include "NWK_INTERFACE/Include/protocol.h"
#ifdef HAVE_RPL
#include "RPL/rpl_control.h"
#ifdef HAVE_RPL
#include "RPL/rpl_data.h"
#endif
#include "RPL/rpl_protocol.h"
@ -44,6 +44,8 @@
#include "common_functions.h"
#include "6LoWPAN/ND/nd_router_object.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_common.h"
#define TRACE_GROUP "icmp"
@ -420,6 +422,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
uint8_t target[16];
uint8_t dummy_sllao[16];
bool proxy = false;
const uint8_t *sllao;
const uint8_t *aro;
@ -439,7 +442,9 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
sllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_SRC_LL_ADDR, 0);
/* If no SLLAO, ignore ARO (RFC 6775 6.5) */
if (sllao && cur->ipv6_neighbour_cache.recv_addr_reg) {
/* This rule can be bypassed by setting flag "use_eui64_as_slla_in_aro" to true */
if (cur->ipv6_neighbour_cache.recv_addr_reg &&
(cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro || sllao)) {
aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 0);
} else {
aro = NULL;
@ -450,6 +455,15 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
goto drop;
}
/* If there was no SLLAO on ARO, use mac address to create dummy one... */
if (aro && !sllao && cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
dummy_sllao[0] = ICMPV6_OPT_SRC_LL_ADDR; // Type
dummy_sllao[1] = 2; // Length = 2x8 bytes
memcpy(dummy_sllao + 2, aro + 8, 8); // EUI-64
memset(dummy_sllao + 10, 0, 6); // Padding
sllao = dummy_sllao;
}
// Skip the 4 reserved bytes
dptr += 4;
@ -529,7 +543,7 @@ drop:
}
int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
{
int ret_val = -1;
@ -564,7 +578,7 @@ void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur
}
#endif // HAVE_IPV6_ND
if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
{
if_address_entry_t *address_entry;
uint8_t ipv6_address[16];
@ -774,7 +788,7 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
ptr += 4;
uint32_t preferred_lifetime = common_read_32_bit(ptr);
ptr += 8; //Update 32-bit time and reserved 32-bit
uint8_t *prefix_ptr = ptr;
const uint8_t *prefix_ptr = ptr;
//Check is L Flag active
if (prefix_flags & PIO_L) {
@ -990,6 +1004,10 @@ static buffer_t *icmpv6_na_handler(buffer_t *buf)
}
ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, flags, buf->dst_sa.addr_type, buf->dst_sa.address);
if (ws_info(cur) && neighbour_entry->state == IP_NEIGHBOUR_REACHABLE) {
tr_debug("NA neigh update");
ws_common_neighbor_update(cur, target);
}
drop:
return buffer_free(buf);
@ -1323,7 +1341,7 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
} else {
/* RFC 4861 7.2.2. says we should use the source of traffic prompting the NS, if possible */
/* This is also used to specify the address for ARO messages */
if (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr)) {
if (aro || (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr))) {
memcpy(buf->src_sa.address, prompting_src_addr, 16);
} else {
/* Otherwise, according to RFC 4861, we could use any address.
@ -1347,8 +1365,16 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
}
}
/* SLLAO is required if we're sending an ARO */
/* This rule can be bypassed with flag use_eui64_as_slla_in_aro */
if (!cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa.address);
}
/* If ARO Success sending is omitted, MAC ACK is used instead */
/* Setting callback for receiving ACK from adaptation layer */
if (aro && cur->ipv6_neighbour_cache.omit_aro_success) {
buf->ack_receive_cb = rpl_control_address_register_done;
}
}
buf->src_sa.addr_type = ADDR_IPV6;
/* NS packets are implicitly on-link. If we ever find ourselves sending an
@ -1481,6 +1507,12 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
tr_debug("Build NA");
/* Check if ARO status == success, then sending can be omitted with flag */
if (aro && cur->ipv6_neighbour_cache.omit_aro_success && aro->status == ARO_SUCCESS) {
tr_debug("Omit success reply");
return NULL;
}
buffer_t *buf = buffer_get(8 + 16 + 16 + 16); /* fixed, target addr, target ll addr, aro */
if (!buf) {
return NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -140,8 +140,8 @@ extern void icmpv6_recv_ra_routes(struct protocol_interface_info_entry *cur, boo
extern void icmpv6_recv_ra_prefixes(struct protocol_interface_info_entry *cur, bool enable);
extern void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len);
extern int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime);
extern struct if_address_entry *icmpv6_slaac_address_add(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src);
extern int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime);
extern struct if_address_entry *icmpv6_slaac_address_add(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src);
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* Copyright (c) 2015-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* Copyright (c) 2013-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010-2017, Arm Limited and affiliates.
* Copyright (c) 2008, 2010-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2017, Arm Limited and affiliates.
* Copyright (c) 2011-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -110,7 +110,7 @@ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspac
#endif
buf->size = total_size;
} else {
tr_error("buffer_get failed: alloc(%zd)", sizeof(buffer_t) + total_size);
tr_error("buffer_get failed: alloc(%d)", (int) sizeof(buffer_t) + total_size);
}
protocol_stats_update(STATS_BUFFER_ALLOC, 1);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010-2017, Arm Limited and affiliates.
* Copyright (c) 2008, 2010-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -96,6 +96,8 @@ typedef struct if_address_entry {
bool temporary:1; // RFC 4941 temporary address
bool tentative:1; // Tentative address (Duplicate Address Detection running)
bool group_added:1; // Solicited-Node group added
uint8_t addr_reg_pend; // Bitmask for pending address registrations. Based on RPL path control bits
uint8_t addr_reg_done; // Bitmask for address registration done. Based on RPL path control bits
if_address_source_t source; //
if_address_callback_fn *cb; // Address protocol callback function
void *data; // Address protocol data

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2017, Arm Limited and affiliates.
* Copyright (c) 2008-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -228,6 +228,7 @@ typedef struct buffer {
uint8_t trickle_data_field[4];
buffer_options_t options; /*!< Additional signal info etc */
buffer_routing_info_t *route; /* A pointer last to try to get neat alignment for data */
void (*ack_receive_cb)(struct buffer *buffer_ptr, uint8_t status); /*!< ACK receive callback. If set, will be called when TX is done */
uint8_t buf[]; /*!< Trailing buffer data */
} buffer_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2015, 2017, Arm Limited and affiliates.
* Copyright (c) 2008-2015, 2017-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -1396,6 +1396,10 @@ buffer_t *socket_tx_buffer_event(buffer_t *buf, uint8_t status)
* and we mapped straight to MAC address).
*/
if (buf->ack_receive_cb) {
buf->ack_receive_cb(buf, status);
}
/* Suppress events once socket orphaned */
if (!buf->socket || (buf->socket->flags & (SOCKET_FLAG_PENDING|SOCKET_FLAG_CLOSED))) {
return buf;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -106,7 +106,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
// coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return
DHCPV6_server_service_remove_GUA_from_neighcache(protocol_stack_interface_info_get_by_id(serverBase->interfaceId), nonTemporalAddress.requestedAddress);
}
if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix, NULL) == -1) {
if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix) == -1) {
// No nanostack BBR present we will put entry for application implemented BBR
ipv6_route_t *route = ipv6_route_add_with_info(dhcp_allocated_address->nonTemporalAddress, 128, serverBase->interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,serverBase->guaPrefix,0, nonTemporalAddress.validLifeTime, 0);
if (!route) {
@ -114,7 +114,6 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -139,6 +139,9 @@ typedef struct protocol_interface_rf_mac_setup {
bool macUpState;
bool shortAdressValid: 1; //Define Dynamic src address to mac16 when it is true
bool beaconSrcAddressModeLong: 1; //This force beacon src to mac64 otherwise shortAdressValid will define type
bool mac_extension_enabled:1;
bool mac_ack_tx_active:1;
bool mac_frame_pending:1;
uint16_t mac_short_address;
uint16_t pan_id;
uint8_t mac64[8];
@ -154,6 +157,8 @@ typedef struct protocol_interface_rf_mac_setup {
bool macProminousMode:1;
bool macGTSPermit:1;
bool mac_security_enabled:1;
/* Let trough packet which is secured properly (MIC authenticated group key) and src address is 64-bit*/
bool mac_security_bypass_unknow_device:1;
/* Load balancing need this feature */
bool macAcceptAnyBeacon:1;
@ -169,6 +174,7 @@ typedef struct protocol_interface_rf_mac_setup {
bool macRfRadioTxActive:1;
bool macBroadcastDisabled:1;
bool scan_active:1;
bool rf_csma_extension_supported:1;
/* CSMA Params */
unsigned macMinBE:4;
unsigned macMaxBE:4;
@ -201,6 +207,7 @@ typedef struct protocol_interface_rf_mac_setup {
uint8_t mac_cca_retry;
uint8_t mac_ack_wait_duration;
uint8_t mac_mlme_retry_max;
uint8_t aUnitBackoffPeriod;
/* Indirect queue parameters */
struct mac_pre_build_frame *indirect_pd_data_request_queue;
arm_event_t mac_mcps_timer_event;
@ -217,6 +224,8 @@ typedef struct protocol_interface_rf_mac_setup {
int8_t cca_timer_id;
int8_t bc_timer_id;
uint32_t mlme_tick_count;
uint32_t symbol_rate;
uint32_t symbol_time_us;
uint8_t max_ED;
uint16_t mlme_ED_counter;
mac_tx_status_t mac_tx_status;
@ -260,6 +269,10 @@ typedef struct protocol_interface_rf_mac_setup {
#define MAC_FCF_ACK_REQ_BIT_SHIFT 5
#define MAC_FCF_INTRA_PANID_MASK 0x0040
#define MAC_FCF_INTRA_PANID_SHIFT 6
#define MAC_FCF_SEQ_NUM_SUPPRESS_MASK 0x0100
#define MAC_FCF_SEQ_NUM_SUPPRESS_SHIFT 8
#define MAC_FCF_IE_PRESENTS_MASK 0x0200
#define MAC_FCF_IE_PRESENTS_SHIFT 9
#define MAC_FCF_DST_ADDR_MASK 0x0c00
#define MAC_FCF_DST_ADDR_SHIFT 10
#define MAC_FCF_VERSION_MASK 0x3000

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* Copyright (c) 2016-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -57,7 +57,12 @@ uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api)
if (!mac_setup) {
return 0;
}
return dev_get_phy_datarate(mac_setup->dev_driver->phy_driver, mac_setup->mac_channel_list.channel_page);
uint32_t datarate = dev_get_phy_datarate(mac_setup->dev_driver->phy_driver, mac_setup->mac_channel_list.channel_page);
// If datarate is not set, use default 250kbit/s.
if (!datarate) {
datarate = 250000;
}
return datarate;
}
int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number)
@ -66,9 +71,8 @@ int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number)
if (!mac_setup) {
return -1;
}
// If TX is active, send internal CCA fail event. MAC state machine would crash without TX done event.
if (mac_setup->macRfRadioTxActive == true) {
mac_setup->dev_driver->phy_driver->phy_tx_done_cb(mac_setup->dev_driver->id, 1, PHY_LINK_TX_FAIL, 0, 0);
if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && mac_setup->active_pd_data_request->asynch_request)) {
return -1;
}
return mac_mlme_rf_channel_change(mac_setup, channel_number);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* Copyright (c) 2014-2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,6 +26,7 @@
#include "mac_filter.h"
#include "mac_common_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"

Some files were not shown because too many files have changed in this diff Show More