mirror of https://github.com/ARMmbed/mbed-os.git
Merge commit 'b0e699fe3e03f574aa2b6d74ff56a024d6e1d508'
* commit 'b0e699fe3e03f574aa2b6d74ff56a024d6e1d508': Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 715ae9a693..3183d87e41pull/14169/head
commit
0c4294b1af
File diff suppressed because it is too large
Load Diff
|
@ -132,6 +132,9 @@ typedef struct fhss_ws_configuration {
|
|||
/** Wi-SUN specific unicast channel mask */
|
||||
uint32_t unicast_channel_mask[8];
|
||||
|
||||
/** Channel mask size */
|
||||
uint16_t channel_mask_size;
|
||||
|
||||
/** Vendor defined channel function. */
|
||||
fhss_vendor_defined_cf *vendor_defined_cf;
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ typedef enum {
|
|||
} mlme_primitive;
|
||||
|
||||
/**
|
||||
* \struct mac_description_storage_size_t
|
||||
* \struct mac_description_storage_size_s
|
||||
* \brief Container for MAC storage sizes.
|
||||
*/
|
||||
typedef struct mac_description_storage_size_s {
|
||||
|
@ -305,7 +305,7 @@ struct mac_api_s {
|
|||
};
|
||||
|
||||
/**
|
||||
* \struct mac_statistics_t
|
||||
* \struct mac_statistics_s
|
||||
* \brief MAC statistics structure.
|
||||
*/
|
||||
typedef struct mac_statistics_s {
|
||||
|
|
|
@ -103,7 +103,7 @@ typedef enum arm_library_event_type_e {
|
|||
#define SOCKET_BIND_DONE SOCKET_CONNECT_DONE /**< Backward compatibility */
|
||||
#define SOCKET_BIND_FAIL SOCKET_CONNECT_FAIL /**< Backward compatibility */
|
||||
#define SOCKET_BIND_AUTH_FAIL SOCKET_CONNECT_AUTH_FAIL /**< Backward compatibility */
|
||||
/* @} */
|
||||
/** @} */
|
||||
|
||||
/** Network security levels. */
|
||||
typedef enum net_security_t {
|
||||
|
@ -1228,3 +1228,4 @@ extern const cca_threshold_table_s *arm_nwk_get_cca_threshold_table(int8_t inter
|
|||
}
|
||||
#endif
|
||||
#endif /* NET_INTERFACE_H_ */
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ typedef enum pana_client_nvm_update_process_t {
|
|||
} pana_client_nvm_update_process_t;
|
||||
|
||||
/*!
|
||||
* \struct wpan_nvm_params_t
|
||||
* \struct wpan_nvm_params
|
||||
* \brief Network nvm parameters.
|
||||
*/
|
||||
typedef struct wpan_nvm_params {
|
||||
|
|
|
@ -52,7 +52,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*!
|
||||
* \enum net_host_mode_t
|
||||
* \enum net_host_mode
|
||||
* \brief Sleepy host states.
|
||||
*/
|
||||
typedef enum net_host_mode {
|
||||
|
|
|
@ -36,7 +36,7 @@ typedef struct ns_mdns *ns_mdns_t; /**< Instance */
|
|||
typedef struct ns_mdns_service *ns_mdns_service_t; /**< Service instance */
|
||||
|
||||
/*!
|
||||
* \struct ns_mdns_service_param_t
|
||||
* \struct ns_mdns_service_param
|
||||
* \brief Structure for mDNS service parameters
|
||||
*/
|
||||
typedef struct ns_mdns_service_param {
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct nwk_stats_t {
|
|||
/* MAC */
|
||||
uint16_t adapt_layer_tx_queue_size; /**< Adaptation layer direct TX queue size. */
|
||||
uint16_t adapt_layer_tx_queue_peak; /**< Adaptation layer direct TX queue size peak. */
|
||||
uint32_t adapt_layer_tx_congestion_drop; /**< Adaptation layer direct TX randon early detection drop packet. */
|
||||
} nwk_stats_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,6 +48,7 @@ extern "C" {
|
|||
#define ARM_AES_MBEDTLS_CONTEXT_MIN 1 /**</ event loop use only */
|
||||
#endif
|
||||
|
||||
/** AES context */
|
||||
typedef struct arm_aes_context arm_aes_context_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -175,6 +175,25 @@ typedef enum {
|
|||
MODULATION_INDEX_UNDEFINED ///< Modulation index undefined
|
||||
} phy_modulation_index_e;
|
||||
|
||||
/** OFDM option */
|
||||
typedef enum {
|
||||
OFDM_OPTION_1 = 1, ///< OFDM option 1
|
||||
OFDM_OPTION_2 = 2, ///< OFDM option 2
|
||||
OFDM_OPTION_3 = 3, ///< OFDM option 3
|
||||
OFDM_OPTION_4 = 4 ///< OFDM option 4
|
||||
} phy_ofdm_option_e;
|
||||
|
||||
/** Modulation and coding scheme (OFDM) */
|
||||
typedef enum {
|
||||
OFDM_MCS_0 = 0, ///< OFDM MCS 0
|
||||
OFDM_MCS_1 = 1, ///< OFDM MCS 1
|
||||
OFDM_MCS_2 = 2, ///< OFDM MCS 2
|
||||
OFDM_MCS_3 = 3, ///< OFDM MCS 3
|
||||
OFDM_MCS_4 = 4, ///< OFDM MCS 4
|
||||
OFDM_MCS_5 = 5, ///< OFDM MCS 5
|
||||
OFDM_MCS_6 = 6 ///< OFDM MCS 6
|
||||
} phy_ofdm_mcs_e;
|
||||
|
||||
/**
|
||||
* @brief enum phy_802_15_4_mode_t IEEE 802.15.4 mode
|
||||
*
|
||||
|
@ -192,6 +211,9 @@ typedef struct phy_rf_channel_configuration_s {
|
|||
uint16_t number_of_channels; ///< Number of channels
|
||||
phy_modulation_e modulation; ///< Modulation scheme
|
||||
phy_modulation_index_e modulation_index; ///< Modulation index
|
||||
bool fec; ///< Forward error correction, true - enabled, false - disabled
|
||||
phy_ofdm_option_e ofdm_option; ///< OFDM option
|
||||
phy_ofdm_mcs_e ofdm_mcs; ///< OFDM modulation and coding scheme
|
||||
} phy_rf_channel_configuration_s;
|
||||
|
||||
/** Channel page configuration */
|
||||
|
|
|
@ -196,7 +196,7 @@ typedef struct socket_callback_t {
|
|||
} socket_callback_t;
|
||||
|
||||
/*!
|
||||
* \struct ns_msghdr_t
|
||||
* \struct ns_msghdr
|
||||
* \brief Normal IP socket message structure for socket_recvmsg() and socket_sendmsg().
|
||||
*/
|
||||
|
||||
|
@ -211,7 +211,7 @@ typedef struct ns_msghdr {
|
|||
} ns_msghdr_t;
|
||||
|
||||
/*!
|
||||
* \struct ns_cmsghdr_t
|
||||
* \struct ns_cmsghdr
|
||||
* \brief Control messages.
|
||||
*/
|
||||
typedef struct ns_cmsghdr {
|
||||
|
@ -242,7 +242,7 @@ typedef struct ns_cmsghdr {
|
|||
#define NS_MSG_LEGACY0 0x4000
|
||||
///@}
|
||||
/*!
|
||||
* \struct ns_in6_pktinfo_t
|
||||
* \struct ns_in6_pktinfo
|
||||
* \brief IPv6 packet info which is used for socket_recvmsg() socket_sendmsg().
|
||||
*/
|
||||
typedef struct ns_in6_pktinfo {
|
||||
|
|
|
@ -96,7 +96,8 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
|||
#define BBR_GUA_ROUTE 0x0002 /**< More specific route is added for GUA prefix */
|
||||
#define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */
|
||||
#define BBR_DEFAULT_ROUTE 0x0008 /**< Add default route parameter to DIO */
|
||||
#define BBR_REQUIRE_DAO_REFRESH 0x0010 /**< Do not increment PAN version number when active forces DAO update from nodes*/
|
||||
#define BBR_REQUIRE_DAO_REFRESH 0x0000 /**< Deprecated DAO Refresh is now the default functionality*/
|
||||
#define BBR_PERIODIC_VERSION_INC 0x0010 /**< Increment PAN version number Periodically*/
|
||||
#define BBR_GUA_SLAAC 0x0020 /**< in Global prefix use SLAAC address generation to reduce traffic during bootstrap */
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file ws_management_if.h
|
||||
* \file ws_management_api.h
|
||||
* \brief Wi-SUN management interface.
|
||||
*
|
||||
* This interface is used for configuring Wi-SUN devices.
|
||||
|
@ -37,61 +37,63 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/* Regulatory domain values*/
|
||||
#define REG_DOMAIN_WW 0x00 // World wide
|
||||
#define REG_DOMAIN_NA 0x01 // North America
|
||||
#define REG_DOMAIN_JP 0x02 // Japan
|
||||
#define REG_DOMAIN_EU 0x03 // European Union
|
||||
#define REG_DOMAIN_CH 0x04 // China
|
||||
#define REG_DOMAIN_IN 0x05 // India
|
||||
#define REG_DOMAIN_MX 0x06 //
|
||||
#define REG_DOMAIN_BZ 0x07 // Brazil
|
||||
#define REG_DOMAIN_AZ 0x08 // Australia
|
||||
#define REG_DOMAIN_NZ 0x08 // New zealand
|
||||
#define REG_DOMAIN_KR 0x09 // Korea
|
||||
#define REG_DOMAIN_PH 0x0A //
|
||||
#define REG_DOMAIN_MY 0x0B //
|
||||
#define REG_DOMAIN_HK 0x0C //
|
||||
#define REG_DOMAIN_SG 0x0D // band 866-869
|
||||
#define REG_DOMAIN_TH 0x0E //
|
||||
#define REG_DOMAIN_VN 0x0F //
|
||||
#define REG_DOMAIN_SG_H 0x10 // band 920-925
|
||||
#define REG_DOMAIN_WW 0x00 /**< World wide */
|
||||
#define REG_DOMAIN_NA 0x01 /**< North America */
|
||||
#define REG_DOMAIN_JP 0x02 /**< Japan */
|
||||
#define REG_DOMAIN_EU 0x03 /**< European Union */
|
||||
#define REG_DOMAIN_CH 0x04 /**< China */
|
||||
#define REG_DOMAIN_IN 0x05 /**< India */
|
||||
#define REG_DOMAIN_MX 0x06 /**< Mexico */
|
||||
#define REG_DOMAIN_BZ 0x07 /**< Brazil */
|
||||
#define REG_DOMAIN_AZ 0x08 /**< Australia */
|
||||
#define REG_DOMAIN_NZ 0x08 /**< New zealand */
|
||||
#define REG_DOMAIN_KR 0x09 /**< Korea */
|
||||
#define REG_DOMAIN_PH 0x0A /**< Philippines */
|
||||
#define REG_DOMAIN_MY 0x0B /**< Malaysia */
|
||||
#define REG_DOMAIN_HK 0x0C /**< Hong Kong */
|
||||
#define REG_DOMAIN_SG 0x0D /**< Singapore band 866-869 */
|
||||
#define REG_DOMAIN_TH 0x0E /**< Thailand */
|
||||
#define REG_DOMAIN_VN 0x0F /**< Vietnam */
|
||||
#define REG_DOMAIN_SG_H 0x10 /**< Singapore band 920-925 */
|
||||
|
||||
#define OPERATING_MODE_1a 0x1a
|
||||
#define OPERATING_MODE_1b 0x1b
|
||||
#define OPERATING_MODE_2a 0x2a
|
||||
#define OPERATING_MODE_2b 0x2b
|
||||
#define OPERATING_MODE_3 0x03
|
||||
#define OPERATING_MODE_4a 0x4a
|
||||
#define OPERATING_MODE_4b 0x4b
|
||||
#define OPERATING_MODE_5 0x05
|
||||
#define OPERATING_MODE_1a 0x1a /**< 50, 0,5 */
|
||||
#define OPERATING_MODE_1b 0x1b /**< 50, 1.0 */
|
||||
#define OPERATING_MODE_2a 0x2a /**< 100, 0,5 */
|
||||
#define OPERATING_MODE_2b 0x2b /**< 100, 1.0 */
|
||||
#define OPERATING_MODE_3 0x03 /**< 150, 0.5 */
|
||||
#define OPERATING_MODE_4a 0x4a /**< 200, 0.5 */
|
||||
#define OPERATING_MODE_4b 0x4b /**< 200, 1.0 */
|
||||
#define OPERATING_MODE_5 0x05 /**< 300, 0.5 */
|
||||
|
||||
#define CHANNEL_FUNCTION_FIXED 0x00 // Fixed channel
|
||||
#define CHANNEL_FUNCTION_TR51CF 0x01 // TR51CF
|
||||
#define CHANNEL_FUNCTION_DH1CF 0x02 // Direct Hash
|
||||
#define CHANNEL_FUNCTION_VENDOR_DEFINED 0x03 // vendor given channel hop schedule
|
||||
#define CHANNEL_FUNCTION_FIXED 0x00 /**< Fixed channel */
|
||||
#define CHANNEL_FUNCTION_TR51CF 0x01 /**< TR51CF */
|
||||
#define CHANNEL_FUNCTION_DH1CF 0x02 /**< Direct Hash */
|
||||
#define CHANNEL_FUNCTION_VENDOR_DEFINED 0x03 /**< vendor given channel hop schedule */
|
||||
|
||||
#define CHANNEL_SPACING_200 0x00 // 200 khz
|
||||
#define CHANNEL_SPACING_400 0x01 // 400 khz
|
||||
#define CHANNEL_SPACING_600 0x02 // 600 khz
|
||||
#define CHANNEL_SPACING_100 0x03 // 100 khz
|
||||
#define CHANNEL_SPACING_250 0x04 // 250 khz
|
||||
#define CHANNEL_SPACING_200 0x00 /**< 200 khz */
|
||||
#define CHANNEL_SPACING_400 0x01 /**< 400 khz */
|
||||
#define CHANNEL_SPACING_600 0x02 /**< 600 khz */
|
||||
#define CHANNEL_SPACING_100 0x03 /**< 100 khz */
|
||||
#define CHANNEL_SPACING_250 0x04 /**< 250 khz */
|
||||
#define CHANNEL_SPACING_800 0x05 /**< 800 khz */
|
||||
#define CHANNEL_SPACING_1200 0x06 /**< 1200 khz */
|
||||
|
||||
/*
|
||||
* Network Size definitions are device amount in hundreds of devices.
|
||||
* These definitions are meant to give some estimates of sizes. Any value can be given as parameter
|
||||
*/
|
||||
|
||||
#define NETWORK_SIZE_CERTIFICATE 0x00 // Network configuration used in Wi-SUN certification
|
||||
#define NETWORK_SIZE_SMALL 0x01 // Small networks
|
||||
#define NETWORK_SIZE_MEDIUM 0x08 // 100 - 800 device networks are medium sized
|
||||
#define NETWORK_SIZE_LARGE 0x0F // 800 - 1500 device networks are large
|
||||
#define NETWORK_SIZE_XLARGE 0x19 // 2500+ devices
|
||||
#define NETWORK_SIZE_AUTOMATIC 0xFF
|
||||
#define NETWORK_SIZE_CERTIFICATE 0x00 /**< Network configuration used in Wi-SUN certification */
|
||||
#define NETWORK_SIZE_SMALL 0x01 /**< Small networks */
|
||||
#define NETWORK_SIZE_MEDIUM 0x08 /**< 100 - 800 device networks are medium sized */
|
||||
#define NETWORK_SIZE_LARGE 0x0F /**< 800 - 1500 device networks are large */
|
||||
#define NETWORK_SIZE_XLARGE 0x19 /**< 2500+ devices */
|
||||
#define NETWORK_SIZE_AUTOMATIC 0xFF /**< Automatic network size */
|
||||
|
||||
/** Temporary API change flag. this will be removed when new version of API is implemented on applications
|
||||
*
|
||||
*/
|
||||
#define WS_MANAGEMENT_API_VER_2
|
||||
#define WS_MANAGEMENT_API_VER_2 /**< Management API version */
|
||||
|
||||
/**
|
||||
* \brief Struct ws_statistics defines the Wi-SUN statistics storage structure.
|
||||
|
@ -184,6 +186,83 @@ int ws_management_network_name_validate(
|
|||
int8_t interface_id,
|
||||
char *network_name_ptr);
|
||||
|
||||
/**
|
||||
* Configure PHY mode ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
*
|
||||
* Change the default configuration for Wi-SUN PHY operation.
|
||||
*
|
||||
* Supported values:
|
||||
* FSK without FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 1 50 0.5
|
||||
* 2 50 1.0
|
||||
* 3 100 0.5
|
||||
* 4 100 1.0
|
||||
* 5 150 0.5
|
||||
* 6 200 0.5
|
||||
* 7 200 1.0
|
||||
* 8 300 0.5
|
||||
*
|
||||
* FSK with FEC:
|
||||
* PHY mode ID | Symbol Rate (kbps) | Modulation Index
|
||||
* 17 50 0.5
|
||||
* 18 50 1.0
|
||||
* 19 100 0.5
|
||||
* 20 100 1.0
|
||||
* 21 150 0.5
|
||||
* 22 200 0.5
|
||||
* 23 200 1.0
|
||||
* 24 300 0.5
|
||||
*
|
||||
* OFDM:
|
||||
* PHY mode ID | Option | MCS | Data rate (kbps)
|
||||
* 34 1 2 400
|
||||
* 35 1 3 800
|
||||
* 36 1 4 1200
|
||||
* 37 1 5 1600
|
||||
* 38 1 6 2400
|
||||
* 51 2 3 400
|
||||
* 52 2 4 600
|
||||
* 53 2 5 800
|
||||
* 54 2 6 1200
|
||||
* 68 3 4 300
|
||||
* 69 3 5 400
|
||||
* 70 3 6 600
|
||||
* 84 4 4 150
|
||||
* 85 4 5 200
|
||||
* 86 4 6 300
|
||||
*
|
||||
* if value of 255 is given then previous value is used.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param phy_mode_id PHY mode ID. Default 255 (not used).
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
int ws_management_phy_mode_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id);
|
||||
|
||||
/**
|
||||
* Configure Channel plan ID of Wi-SUN stack as defined by Wi-SUN FAN 1.1.
|
||||
*
|
||||
* Change the default channel configuration for Wi-SUN.
|
||||
*
|
||||
* Supported values: TBD
|
||||
*
|
||||
* if value of 255 is given then previous value is used.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param channel_plan_id Channel plan ID. Default 255 (not used).
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
int ws_management_channel_plan_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_plan_id);
|
||||
|
||||
/**
|
||||
* Configure regulatory domain of Wi-SUN stack.
|
||||
*
|
||||
|
|
|
@ -799,15 +799,15 @@ bool protocol_6lowpan_latency_estimate_get(int8_t interface_id, uint32_t *latenc
|
|||
|
||||
if (cur_interface->eth_mac_api) {
|
||||
// either PPP or Ethernet interface.
|
||||
latency_estimate = 100;
|
||||
latency_estimate = 1000;
|
||||
} else if (thread_info(cur_interface)) {
|
||||
// thread network
|
||||
latency_estimate = 2000;
|
||||
latency_estimate = 5000;
|
||||
} else if (ws_info(cur_interface)) {
|
||||
latency_estimate = ws_common_latency_estimate_get(cur_interface);
|
||||
} else {
|
||||
// 6LoWPAN ND
|
||||
latency_estimate = 8000;
|
||||
latency_estimate = 20000;
|
||||
}
|
||||
|
||||
if (latency_estimate != 0) {
|
||||
|
|
|
@ -930,7 +930,7 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
|
|||
/* TODO - check hard upper limit on registrations? */
|
||||
if (ws_info(cur_interface)) {
|
||||
|
||||
aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64);
|
||||
aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64, aro_out->lifetime);
|
||||
if (aro_out->status != ARO_SUCCESS) {
|
||||
aro_out->present = true;
|
||||
return true;
|
||||
|
|
|
@ -42,13 +42,14 @@
|
|||
#include "MLE/mle.h"
|
||||
#include "Service_Libs/mle_service/mle_service_api.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#ifdef HAVE_RPL
|
||||
#include "RPL/rpl_data.h"
|
||||
#endif
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
|
||||
#include "Service_Libs/random_early_detection/random_early_detection_api.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);
|
||||
|
@ -60,6 +61,8 @@ typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, bu
|
|||
#define tr_debug_extra(...)
|
||||
#endif
|
||||
|
||||
#define ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE 20
|
||||
|
||||
typedef struct {
|
||||
uint16_t tag; /*!< Fragmentation datagram TAG ID */
|
||||
uint16_t size; /*!< Datagram Total Size (uncompressed) */
|
||||
|
@ -93,6 +96,8 @@ typedef struct {
|
|||
fragmenter_tx_list_t activeUnicastList; //Unicast packets waiting data confirmation from MAC
|
||||
buffer_list_t directTxQueue; //Waiting free tx process
|
||||
uint16_t directTxQueue_size;
|
||||
uint16_t directTxQueue_level;
|
||||
uint16_t activeTxList_size;
|
||||
uint16_t indirect_big_packet_threshold;
|
||||
uint16_t max_indirect_big_packets_total;
|
||||
uint16_t max_indirect_small_packets_per_child;
|
||||
|
@ -103,6 +108,17 @@ typedef struct {
|
|||
ns_list_link_t link; /*!< List link entry */
|
||||
} fragmenter_interface_t;
|
||||
|
||||
#define LOWPAN_ACTIVE_UNICAST_ONGOING_MAX 10
|
||||
|
||||
/* Minimum buffer amount and memory size to ensure operation even in out of memory situation
|
||||
*/
|
||||
#define LOWPAN_MEM_LIMIT_MIN_QUEUE 10
|
||||
#define LOWPAN_MEM_LIMIT_MIN_MEMORY 10000
|
||||
#define LOWPAN_MEM_LIMIT_REMOVE_NORMAL 3000 // Remove when approaching memory limit
|
||||
#define LOWPAN_MEM_LIMIT_REMOVE_MAX 10000 // Remove when at memory limit
|
||||
|
||||
|
||||
|
||||
static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link);
|
||||
|
||||
/* Adaptation interface local functions */
|
||||
|
@ -203,11 +219,22 @@ static struct protocol_interface_info_entry *lowpan_adaptation_network_interface
|
|||
}
|
||||
|
||||
|
||||
static void lowpan_adaptation_tx_queue_level_update(fragmenter_interface_t *interface_ptr)
|
||||
{
|
||||
if (interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level + ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE ||
|
||||
interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level - ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE) {
|
||||
interface_ptr->directTxQueue_level = interface_ptr->directTxQueue_size;
|
||||
tr_info("Adaptation layer TX queue size %u Active MAC tx request %u", interface_ptr->directTxQueue_level, interface_ptr->activeTxList_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf)
|
||||
{
|
||||
buffer_t *lower_priority_buf = NULL;
|
||||
|
||||
ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) {
|
||||
|
||||
if (cur->priority < buf->priority) {
|
||||
lower_priority_buf = cur;
|
||||
break;
|
||||
|
@ -220,6 +247,7 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
|
|||
ns_list_add_to_end(&interface_ptr->directTxQueue, buf);
|
||||
}
|
||||
interface_ptr->directTxQueue_size++;
|
||||
lowpan_adaptation_tx_queue_level_update(interface_ptr);
|
||||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
|
||||
|
@ -233,6 +261,7 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa
|
|||
if (lowpan_buffer_tx_allowed(interface_ptr, buf)) {
|
||||
ns_list_remove(&interface_ptr->directTxQueue, buf);
|
||||
interface_ptr->directTxQueue_size--;
|
||||
lowpan_adaptation_tx_queue_level_update(interface_ptr);
|
||||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
return buf;
|
||||
}
|
||||
|
@ -365,6 +394,9 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si
|
|||
ns_list_init(&interface_ptr->indirect_tx_queue);
|
||||
ns_list_init(&interface_ptr->directTxQueue);
|
||||
ns_list_init(&interface_ptr->activeUnicastList);
|
||||
interface_ptr->activeTxList_size = 0;
|
||||
interface_ptr->directTxQueue_size = 0;
|
||||
interface_ptr->directTxQueue_level = 0;
|
||||
|
||||
ns_list_add_to_end(&fragmenter_interface_list, interface_ptr);
|
||||
|
||||
|
@ -390,13 +422,15 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id)
|
|||
ns_list_remove(&fragmenter_interface_list, interface_ptr);
|
||||
//free active tx process
|
||||
lowpan_list_free(&interface_ptr->activeUnicastList, false);
|
||||
interface_ptr->activeTxList_size = 0;
|
||||
lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf);
|
||||
|
||||
//Free Indirect entry
|
||||
lowpan_list_free(&interface_ptr->indirect_tx_queue, true);
|
||||
|
||||
buffer_free_list(&interface_ptr->directTxQueue);
|
||||
|
||||
interface_ptr->directTxQueue_size = 0;
|
||||
interface_ptr->directTxQueue_level = 0;
|
||||
//Free Dynamic allocated entries
|
||||
ns_dyn_mem_free(interface_ptr->fragment_indirect_tx_buffer);
|
||||
ns_dyn_mem_free(interface_ptr);
|
||||
|
@ -415,6 +449,7 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
|
|||
|
||||
//free active tx process
|
||||
lowpan_list_free(&interface_ptr->activeUnicastList, false);
|
||||
interface_ptr->activeTxList_size = 0;
|
||||
lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf);
|
||||
//Clean fragmented message flag
|
||||
interface_ptr->fragmenter_active = false;
|
||||
|
@ -423,6 +458,8 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
|
|||
lowpan_list_free(&interface_ptr->indirect_tx_queue, true);
|
||||
|
||||
buffer_free_list(&interface_ptr->directTxQueue);
|
||||
interface_ptr->directTxQueue_size = 0;
|
||||
interface_ptr->directTxQueue_level = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -465,6 +502,63 @@ int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_
|
|||
return 0;
|
||||
}
|
||||
|
||||
void lowpan_adaptation_free_heap(bool full_gc)
|
||||
{
|
||||
ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) {
|
||||
// Go through all interfaces and free small amount of memory
|
||||
// This is not very radical, but gives time to recover wthout causing too harsh changes
|
||||
lowpan_adaptation_free_low_priority_packets(interface_ptr->interface_id, full_gc ? LOWPAN_MEM_LIMIT_REMOVE_MAX : LOWPAN_MEM_LIMIT_REMOVE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount)
|
||||
{
|
||||
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
|
||||
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t adaptation_memory = 0;
|
||||
uint16_t adaptation_packets = 0;
|
||||
uint32_t memory_freed = 0;
|
||||
uint16_t packets_freed = 0;
|
||||
|
||||
ns_list_foreach(buffer_t, entry, &interface_ptr->directTxQueue) {
|
||||
adaptation_memory += sizeof(buffer_t) + entry->size;
|
||||
adaptation_packets++;
|
||||
}
|
||||
|
||||
if (interface_ptr->directTxQueue_size < LOWPAN_MEM_LIMIT_MIN_QUEUE) {
|
||||
// Minimum reserved for operations
|
||||
return 0;
|
||||
}
|
||||
if (adaptation_memory < LOWPAN_MEM_LIMIT_MIN_MEMORY) {
|
||||
// Minimum reserved for operations
|
||||
return 0;
|
||||
}
|
||||
if (adaptation_memory - requested_amount < LOWPAN_MEM_LIMIT_MIN_MEMORY) {
|
||||
// only reduse to minimum
|
||||
requested_amount = adaptation_memory - LOWPAN_MEM_LIMIT_MIN_MEMORY;
|
||||
}
|
||||
|
||||
//Only remove last entries from TX queue with low priority
|
||||
ns_list_foreach_reverse_safe(buffer_t, entry, &interface_ptr->directTxQueue) {
|
||||
if (entry->priority == QOS_NORMAL) {
|
||||
memory_freed += sizeof(buffer_t) + entry->size;
|
||||
packets_freed++;
|
||||
ns_list_remove(&interface_ptr->directTxQueue, entry);
|
||||
interface_ptr->directTxQueue_size--;
|
||||
lowpan_adaptation_tx_queue_level_update(interface_ptr);
|
||||
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
|
||||
}
|
||||
if (memory_freed > requested_amount) {
|
||||
// Enough memory freed
|
||||
break;
|
||||
}
|
||||
}
|
||||
tr_info("Adaptation Free low priority packets memory: %" PRIi32 " queue: %d deallocated %" PRIi32 " bytes, %d packets, %" PRIi32 " requested", adaptation_memory, adaptation_packets, memory_freed, packets_freed, requested_amount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size)
|
||||
{
|
||||
|
@ -597,6 +691,7 @@ static fragmenter_tx_entry_t *lowpan_adaptation_tx_process_init(fragmenter_inter
|
|||
return NULL;
|
||||
}
|
||||
ns_list_add_to_end(&interface_ptr->activeUnicastList, tx_entry);
|
||||
interface_ptr->activeTxList_size++;
|
||||
} else {
|
||||
tx_entry = &interface_ptr->active_broadcast_tx_buf;
|
||||
}
|
||||
|
@ -969,6 +1064,13 @@ static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buff
|
|||
if (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_unicast && interface_ptr->activeTxList_size >= LOWPAN_ACTIVE_UNICAST_ONGOING_MAX) {
|
||||
//New TX is not possible there is already too manyactive connecting
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Do not accept more than one active unicast TX per destination
|
||||
if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) {
|
||||
return false;
|
||||
|
@ -992,6 +1094,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
|||
goto tx_error_handler;
|
||||
}
|
||||
|
||||
uint8_t traffic_class = buf->options.traffic_class >> IP_TCLASS_DSCP_SHIFT;
|
||||
|
||||
if (traffic_class == IP_DSCP_EF) {
|
||||
buffer_priority_set(buf, QOS_EXPEDITE_FORWARD);
|
||||
} else if (traffic_class == IP_DSCP_CS6) {
|
||||
//Network Control
|
||||
buffer_priority_set(buf, QOS_NETWORK_CTRL);
|
||||
} else if (traffic_class) {
|
||||
buffer_priority_set(buf, QOS_HIGH);
|
||||
}
|
||||
|
||||
|
||||
//Check packet size
|
||||
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
|
||||
if (fragmented_needed) {
|
||||
|
@ -1010,7 +1124,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
|||
bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess;
|
||||
|
||||
if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) {
|
||||
|
||||
if (buf->priority == QOS_NORMAL) {
|
||||
|
||||
if (random_early_detection_congestion_check(cur->random_early_detection)) {
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
protocol_stats_update(STATS_AL_TX_CONGESTION_DROP, 1);
|
||||
goto tx_error_handler;
|
||||
}
|
||||
}
|
||||
|
||||
lowpan_adaptation_tx_queue_write(interface_ptr, buf);
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1166,6 +1291,7 @@ static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interfa
|
|||
} else if (buf->link_specific.ieee802_15_4.requestAck) {
|
||||
ns_list_remove(&interface_ptr->activeUnicastList, tx_ptr);
|
||||
ns_dyn_mem_free(tx_ptr);
|
||||
interface_ptr->activeTxList_size--;
|
||||
}
|
||||
|
||||
socket_tx_buffer_event_and_free(buf, socket_event);
|
||||
|
@ -1205,7 +1331,6 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
|
|||
tr_error("No data request for this confirmation %u", confirm->msduHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Check status for
|
||||
buffer_t *buf = tx_ptr->buf;
|
||||
|
||||
|
@ -1229,64 +1354,58 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
|
|||
buf->link_specific.ieee802_15_4.rf_channel_switch = false;
|
||||
}
|
||||
|
||||
switch (confirm->status) {
|
||||
|
||||
case MLME_BUSY_CHAN:
|
||||
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
|
||||
break;
|
||||
case MLME_SUCCESS:
|
||||
|
||||
//Check is there more packets
|
||||
if (lowpan_adaptation_tx_process_ready(tx_ptr)) {
|
||||
bool triggered_from_indirect_cache = false;
|
||||
if (tx_ptr->fragmented_data && active_direct_confirm) {
|
||||
//Clean
|
||||
interface_ptr->fragmenter_active = false;
|
||||
}
|
||||
|
||||
if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) {
|
||||
triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr);
|
||||
}
|
||||
|
||||
lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status));
|
||||
|
||||
if (triggered_from_indirect_cache) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
|
||||
if (confirm->status == MLME_SUCCESS) {
|
||||
//Check is there more packets
|
||||
if (lowpan_adaptation_tx_process_ready(tx_ptr)) {
|
||||
bool triggered_from_indirect_cache = false;
|
||||
if (tx_ptr->fragmented_data && active_direct_confirm) {
|
||||
interface_ptr->fragmenter_active = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case MLME_TX_NO_ACK:
|
||||
case MLME_SECURITY_FAIL:
|
||||
case MLME_TRANSACTION_EXPIRED:
|
||||
default:
|
||||
tr_error("MCPS Data fail by status %u", confirm->status);
|
||||
if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) {
|
||||
tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2));
|
||||
} else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
|
||||
tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8));
|
||||
}
|
||||
|
||||
#ifdef HAVE_RPL
|
||||
if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) {
|
||||
if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) {
|
||||
protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (tx_ptr->fragmented_data) {
|
||||
tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end;
|
||||
tx_ptr->buf->buf_ptr -= tx_ptr->orig_size;
|
||||
if (active_direct_confirm) {
|
||||
interface_ptr->fragmenter_active = false;
|
||||
}
|
||||
if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) {
|
||||
triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr);
|
||||
}
|
||||
|
||||
lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status));
|
||||
break;
|
||||
|
||||
if (triggered_from_indirect_cache) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
|
||||
}
|
||||
} else if ((confirm->status == MLME_BUSY_CHAN) && !ws_info(cur)) {
|
||||
lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr);
|
||||
} else {
|
||||
|
||||
|
||||
if (confirm->status == MLME_TRANSACTION_OVERFLOW) {
|
||||
tr_error("MCPS Data fail by MLME_TRANSACTION_OVERFLOW");
|
||||
}
|
||||
|
||||
tr_error("MCPS Data fail by status %u", confirm->status);
|
||||
if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) {
|
||||
tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2));
|
||||
} else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
|
||||
tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8));
|
||||
}
|
||||
|
||||
#ifdef HAVE_RPL
|
||||
if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) {
|
||||
if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) {
|
||||
protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (tx_ptr->fragmented_data) {
|
||||
tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end;
|
||||
tx_ptr->buf->buf_ptr -= tx_ptr->orig_size;
|
||||
if (active_direct_confirm) {
|
||||
interface_ptr->fragmenter_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status));
|
||||
}
|
||||
// When confirmation is for direct transmission, push all allowed buffers to MAC
|
||||
if (active_direct_confirm == true) {
|
||||
|
@ -1295,6 +1414,8 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
|
|||
lowpan_adaptation_interface_tx(cur, buf_from_queue);
|
||||
buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
|
||||
}
|
||||
//Update Average QUEUE
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1492,10 +1613,21 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in
|
|||
}
|
||||
}
|
||||
|
||||
//Check next directTxQueue there may be pending packets also
|
||||
ns_list_foreach_safe(buffer_t, entry, &interface_ptr->directTxQueue) {
|
||||
if (lowpan_tx_buffer_address_compare(&entry->dst_sa, address_ptr, adr_type)) {
|
||||
ns_list_remove(&interface_ptr->directTxQueue, entry);
|
||||
interface_ptr->directTxQueue_size--;
|
||||
//Update Average QUEUE
|
||||
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
|
||||
lowpan_adaptation_tx_queue_level_update(interface_ptr);
|
||||
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id);
|
||||
|
|
|
@ -36,8 +36,13 @@ 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);
|
||||
|
||||
void lowpan_adaptation_free_heap(bool full_gc);
|
||||
|
||||
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount);
|
||||
|
||||
|
||||
/**
|
||||
* \brief call this before normatl TX. This function prepare buffer link spesific metadata and verify packet destination
|
||||
* \brief call this before normal TX. This function prepare buffer link specific metadata and verify packet destination
|
||||
*/
|
||||
struct buffer *lowpan_adaptation_data_process_tx_preprocess(struct protocol_interface_info_entry *cur, struct buffer *buf);
|
||||
|
||||
|
|
|
@ -176,12 +176,12 @@ static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur,
|
|||
//stable version for RPL so slow timer update is ok
|
||||
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME;
|
||||
} else {
|
||||
if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) {
|
||||
// handles also NETWORK_SIZE_CERTIFICATE
|
||||
if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) {
|
||||
// Also handles CONFIG_CERTIFICATE
|
||||
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_SMALL;
|
||||
} else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM) {
|
||||
} else if (ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM) {
|
||||
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_MEDIUM;
|
||||
} else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_LARGE) {
|
||||
} else if (ws_cfg_network_config_get(cur) <= CONFIG_LARGE) {
|
||||
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_LARGE;
|
||||
} else {
|
||||
cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_EXTRA_LARGE;
|
||||
|
@ -712,11 +712,13 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur)
|
|||
return;
|
||||
}
|
||||
tr_debug("Border router version number update");
|
||||
if (configuration & BBR_REQUIRE_DAO_REFRESH) {
|
||||
if (configuration & BBR_PERIODIC_VERSION_INC) {
|
||||
// Periodically increase the version number.
|
||||
// This removes need for DAO, but causes slowness in recovery
|
||||
pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL;
|
||||
} else {
|
||||
// Version number is not periodically increased forcing nodes to check Border router availability using DAO
|
||||
pan_version_timer = 0;
|
||||
} else {
|
||||
pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL;
|
||||
}
|
||||
cur->ws_info->pan_information.pan_version++;
|
||||
// Inconsistent for border router to make information distribute faster
|
||||
|
@ -923,12 +925,16 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options)
|
|||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (protocol_6lowpan_rpl_root_dodag &&
|
||||
options != configuration) {
|
||||
//Configuration changed delete previous setup
|
||||
ws_bbr_routing_stop(cur);
|
||||
if (options == configuration) {
|
||||
return 0;
|
||||
}
|
||||
//Configuration changed
|
||||
configuration = options;
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
// Already active needs to restart
|
||||
ws_bbr_routing_stop(cur);
|
||||
ws_bbr_pan_version_increase(cur);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
(void)interface_id;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#ifdef HAVE_WS
|
||||
#include "ns_types.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "net_interface.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "randLIB.h"
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "Common_Protocols/icmpv6_radv.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "Service_Libs/Trickle/trickle.h"
|
||||
#include "Service_Libs/fhss/channel_list.h"
|
||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||
|
@ -75,6 +77,7 @@
|
|||
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_relay.h"
|
||||
#include "libNET/src/net_dns_internal.h"
|
||||
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
|
||||
|
||||
#define TRACE_GROUP "wsbs"
|
||||
|
||||
|
@ -111,6 +114,10 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa
|
|||
static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur);
|
||||
static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create);
|
||||
static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry);
|
||||
static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur);
|
||||
|
||||
static void ws_bootstrap_asynch_trickle_stop(protocol_interface_info_entry_t *cur);
|
||||
static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur);
|
||||
|
||||
typedef enum {
|
||||
WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/
|
||||
|
@ -163,7 +170,7 @@ void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_ent
|
|||
{
|
||||
mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT);
|
||||
|
||||
if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
|
||||
if (neighbor && neighbor->link_lifetime <= valid_time) {
|
||||
//mlme_device_descriptor_t device_desc;
|
||||
neighbor->lifetime = valid_time;
|
||||
neighbor->link_lifetime = valid_time;
|
||||
|
@ -426,19 +433,47 @@ static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighb
|
|||
ws_nud_state_clean(cur, nud_entry);
|
||||
}
|
||||
}
|
||||
if_address_entry_t *ws_probe_aro_address(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
if (interface->global_address_available) {
|
||||
ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) {
|
||||
if (addr_ipv6_scope(address->address, interface) > IPV6_SCOPE_LINK_LOCAL) {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor, bool nud_process)
|
||||
{
|
||||
//Send NS
|
||||
uint8_t ll_target[16];
|
||||
aro_t aro_temp;
|
||||
//SET ARO and src address pointer to NULL by default
|
||||
aro_t *aro_ptr = NULL;
|
||||
uint8_t *src_address_ptr = NULL;
|
||||
|
||||
ws_bootsrap_create_ll_address(ll_target, neighbor->mac64);
|
||||
if (nud_process) {
|
||||
tr_info("NUD generate NS %u", neighbor->index);
|
||||
} else {
|
||||
tr_info("Probe generate NS %u", neighbor->index);
|
||||
if_address_entry_t *gp_address = ws_probe_aro_address(cur);
|
||||
if (gp_address) {
|
||||
src_address_ptr = gp_address->address;
|
||||
aro_temp.status = ARO_SUCCESS;
|
||||
aro_temp.present = true;
|
||||
memcpy(aro_temp.eui64, cur->mac, 8);
|
||||
//Just Short Test
|
||||
aro_temp.lifetime = 1;
|
||||
aro_ptr = &aro_temp;
|
||||
}
|
||||
}
|
||||
buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL);
|
||||
buffer_t *buffer = icmpv6_build_ns(cur, ll_target, src_address_ptr, true, false, aro_ptr);
|
||||
if (buffer) {
|
||||
buffer->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
protocol_push(buffer);
|
||||
return true;
|
||||
}
|
||||
|
@ -592,8 +627,9 @@ static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded
|
|||
|
||||
static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration)
|
||||
{
|
||||
ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
|
||||
ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
|
||||
fhss_configuration->channel_mask_size = cur->ws_info->hopping_schdule.number_of_channels;
|
||||
ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id);
|
||||
ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id);
|
||||
// using bitwise AND operation for user set channel mask to remove channels not allowed in this device
|
||||
for (uint8_t n = 0; n < 8; n++) {
|
||||
fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n];
|
||||
|
@ -1518,10 +1554,10 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter
|
|||
*/
|
||||
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit);
|
||||
/*
|
||||
* Optimized PAN discovery to select faster the parent if we hear solicit from someone else
|
||||
* Optimized PAN discovery to select the parent faster if we hear solicit from someone else
|
||||
*/
|
||||
|
||||
if (ws_bootstrap_state_discovery(cur) && cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM &&
|
||||
if (ws_bootstrap_state_discovery(cur) && ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM &&
|
||||
cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin * 2) {
|
||||
|
||||
cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin);
|
||||
|
@ -1595,10 +1631,15 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
|||
|
||||
//When Config is learned and USE Parent BS is enabled compare is this new BSI
|
||||
if (cur->ws_info->configuration_learned && cur->ws_info->pan_information.use_parent_bs && ws_bs_ie.broadcast_schedule_identifier != cur->ws_info->hopping_schdule.fhss_bsi) {
|
||||
tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier);
|
||||
cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout;
|
||||
cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi;
|
||||
ws_bootstrap_event_discovery_start(cur);
|
||||
//Accept only next possible BSI number
|
||||
if ((cur->ws_info->hopping_schdule.fhss_bsi + 1) != ws_bs_ie.broadcast_schedule_identifier) {
|
||||
tr_debug("Do not accept a unknown BSI: %u", ws_bs_ie.broadcast_schedule_identifier);
|
||||
} else {
|
||||
tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier);
|
||||
cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout;
|
||||
cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi;
|
||||
ws_bootstrap_event_discovery_start(cur);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2007,7 +2048,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt
|
|||
|
||||
static uint32_t ws_probe_init_time_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) {
|
||||
if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) {
|
||||
return WS_SMALL_PROBE_INIT_BASE_SECONDS;
|
||||
}
|
||||
|
||||
|
@ -2359,11 +2400,30 @@ int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t
|
|||
static int ws_bootstrap_set_domain_rf_config(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
phy_rf_channel_configuration_s rf_configs;
|
||||
memset(&rf_configs, 0, sizeof(phy_rf_channel_configuration_s));
|
||||
|
||||
uint8_t phy_mode_id = cur->ws_info->hopping_schdule.phy_mode_id;
|
||||
if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) ||
|
||||
((phy_mode_id >= 51) && (phy_mode_id <= 54)) ||
|
||||
((phy_mode_id >= 68) && (phy_mode_id <= 70)) ||
|
||||
((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
|
||||
rf_configs.modulation = M_OFDM;
|
||||
rf_configs.datarate = ws_get_datarate_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id);
|
||||
rf_configs.ofdm_option = ws_get_ofdm_option_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id);
|
||||
rf_configs.ofdm_mcs = ws_get_ofdm_mcs_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id);
|
||||
} else {
|
||||
if ((phy_mode_id >= 17) && (phy_mode_id <= 24)) {
|
||||
rf_configs.fec = true;
|
||||
} else {
|
||||
rf_configs.fec = false;
|
||||
}
|
||||
rf_configs.modulation = M_2FSK;
|
||||
rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
}
|
||||
|
||||
rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000;
|
||||
rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing);
|
||||
rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
rf_configs.modulation = M_2FSK;
|
||||
rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels;
|
||||
ws_bootstrap_set_rf_config(cur, rf_configs);
|
||||
return 0;
|
||||
|
@ -2522,6 +2582,12 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
|
|||
// After successful DAO ACK connection to border router is verified
|
||||
cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!cur->ws_info->trickle_pa_running || !cur->ws_info->trickle_pc_running) {
|
||||
//Enable wi-sun asynch adverisment
|
||||
ws_bootstrap_advertise_start(cur);
|
||||
}
|
||||
|
||||
ws_set_fhss_hop(cur);
|
||||
|
@ -2536,6 +2602,12 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
|
|||
*
|
||||
*/
|
||||
|
||||
} else if (event == RPL_EVENT_LOCAL_REPAIR_START) {
|
||||
tr_debug("RPL local repair start");
|
||||
//Disable Asynchs
|
||||
ws_bootstrap_asynch_trickle_stop(cur);
|
||||
ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN);
|
||||
|
||||
} else if (event == RPL_EVENT_DAO_PARENT_ADD) {
|
||||
ws_address_parent_update(cur);
|
||||
}
|
||||
|
@ -3024,9 +3096,9 @@ static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur)
|
|||
tr_debug("Start RPL learn");
|
||||
// routers wait until RPL root is contacted
|
||||
ws_bootstrap_state_change(cur, ER_RPL_SCAN);
|
||||
//For Large network and medium shuold do passive scan
|
||||
if (cur->ws_info->cfg->gen.network_size > NETWORK_SIZE_SMALL) {
|
||||
// Set timeout for check to 30 -60 seconds
|
||||
//For Large network and medium should do passive scan
|
||||
if (ws_cfg_network_config_get(cur) > CONFIG_SMALL) {
|
||||
// Set timeout for check to 30 - 60 seconds
|
||||
cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT);
|
||||
}
|
||||
/* While in Join State 4, if a non Border Router determines it has been unable to communicate with the PAN Border
|
||||
|
@ -3073,7 +3145,7 @@ static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asy
|
|||
uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel;
|
||||
async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32));
|
||||
} else {
|
||||
ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
|
||||
ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id);
|
||||
}
|
||||
|
||||
async_req->channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
|
@ -3272,6 +3344,8 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
|
||||
// All trickle timers stopped to allow entry from any state
|
||||
ws_bootstrap_asynch_trickle_stop(cur);
|
||||
//Init Packet congestion
|
||||
ws_bootstrap_packet_congestion_init(cur);
|
||||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
tr_info("Border router start network");
|
||||
|
@ -3761,4 +3835,78 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_
|
|||
return 0;
|
||||
}
|
||||
|
||||
//Calculate max_packet queue size
|
||||
static uint16_t ws_bootstrap_define_congestin_max_threshold(uint32_t heap_total_size, uint16_t packet_size, uint16_t packet_per_seconds, uint32_t max_delay, uint16_t min_packet_queue_size, uint16_t max_packet_queue_size)
|
||||
{
|
||||
uint32_t max_packet_count = 0;
|
||||
if (heap_total_size) {
|
||||
//Claculate how many packet can be max queue to half of heap
|
||||
max_packet_count = (heap_total_size / 2) / packet_size;
|
||||
}
|
||||
|
||||
//Calculate how many packet is possible to queue for guarantee given max delay
|
||||
uint32_t max_delayded_queue_size = max_delay * packet_per_seconds;
|
||||
|
||||
if (max_packet_count > max_delayded_queue_size) {
|
||||
//Limit queue size by MAX delay
|
||||
max_packet_count = max_delayded_queue_size;
|
||||
}
|
||||
|
||||
if (max_packet_count > max_packet_queue_size) {
|
||||
//Limit queue size by Max
|
||||
max_packet_count = max_packet_queue_size;
|
||||
} else if (max_packet_count < min_packet_queue_size) {
|
||||
//Limit queue size by Min
|
||||
max_packet_count = min_packet_queue_size;
|
||||
}
|
||||
return (uint16_t)max_packet_count;
|
||||
}
|
||||
|
||||
static uint16_t ws_bootstrap_packet_per_seconds(protocol_interface_info_entry_t *cur, uint16_t packet_size)
|
||||
{
|
||||
uint32_t data_rate = ws_common_datarate_get(cur);
|
||||
|
||||
//calculate how many packet is possible send in paper
|
||||
data_rate /= 8 * packet_size;
|
||||
|
||||
//Divide optimal by / 5 because we split TX / RX slots and BC schedule
|
||||
//With Packet size 500 it should return
|
||||
//Return 15 for 300kBits
|
||||
//Return 7 for 150kBits
|
||||
//Return 2 for 50kBits
|
||||
return data_rate / 5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
random_early_detection_free(cur->random_early_detection);
|
||||
cur->random_early_detection = NULL;
|
||||
|
||||
//TODO implement API for HEAP info request
|
||||
uint32_t heap_size;
|
||||
const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat();
|
||||
if (mem_stats) {
|
||||
heap_size = mem_stats->heap_sector_size;
|
||||
} else {
|
||||
heap_size = 0;
|
||||
}
|
||||
|
||||
uint16_t packet_per_seconds = ws_bootstrap_packet_per_seconds(cur, WS_CONGESTION_PACKET_SIZE);
|
||||
|
||||
uint16_t min_th, max_th;
|
||||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_BR_MIN_QUEUE_SIZE, WS_CONGESTION_BR_MAX_QUEUE_SIZE);
|
||||
} else {
|
||||
max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_NODE_MIN_QUEUE_SIZE, WS_CONGESTION_NODE_MAX_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
min_th = max_th / 2;
|
||||
tr_info("Wi-SUN packet congestion minTh %u, maxTh %u, drop probability %u weight %u, Packet/Seconds %u", min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH, packet_per_seconds);
|
||||
cur->random_early_detection = random_early_detection_create(min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH);
|
||||
|
||||
}
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -79,6 +79,32 @@ typedef union {
|
|||
ws_sec_prot_cfg_t sec_prot;
|
||||
} ws_cfgs_t;
|
||||
|
||||
|
||||
typedef struct cfg_devices_in_config {
|
||||
uint8_t max_for_small;
|
||||
uint8_t max_for_medium;
|
||||
uint8_t max_for_large;
|
||||
uint8_t max_for_xlarge;
|
||||
} cfg_devices_in_config_t;
|
||||
|
||||
/* Table for amount of devices that certain configuration should be used
|
||||
*
|
||||
* larger data rates allow more devices to be used with faster settings.
|
||||
*
|
||||
* For example with network the size of 2000 devices we use
|
||||
* Xlrage configuration with 50kbs data rate.
|
||||
* Large configuration with 300kbs data rate.
|
||||
* and with 600kbs data rate it is possible to use medium network settings.
|
||||
*
|
||||
*/
|
||||
const cfg_devices_in_config_t devices_by_datarate[] = {
|
||||
{ 1, 4, 10, 25}, // Configuration for 50 -100kbs
|
||||
{ 1, 8, 15, 25}, // Configuration for 150kbs - 200kbs
|
||||
{ 2, 15, 25, 50}, // Configuration for 300kbs
|
||||
{ 3, 20, 40, 100}, // Configuration for 600kbs - 2400kbs
|
||||
};
|
||||
|
||||
|
||||
static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *external_cfg, uint8_t *cfg_flags, uint8_t *flags);
|
||||
|
||||
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg);
|
||||
|
@ -258,13 +284,13 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_
|
|||
|
||||
ws_cfg_network_size_config_set_size set_function = NULL;
|
||||
|
||||
if (cfg->network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
if (ws_cfg_network_config_get(cur) == CONFIG_CERTIFICATE) {
|
||||
set_function = ws_cfg_network_size_config_set_certificate;
|
||||
} else if (cfg->network_size <= NETWORK_SIZE_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) {
|
||||
} else if (ws_cfg_network_config_get(cur) == CONFIG_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) {
|
||||
set_function = ws_cfg_network_size_config_set_small;
|
||||
} else if (cfg->network_size <= NETWORK_SIZE_MEDIUM) {
|
||||
} else if (ws_cfg_network_config_get(cur) == CONFIG_MEDIUM) {
|
||||
set_function = ws_cfg_network_size_config_set_medium;
|
||||
} else if (cfg->network_size <= NETWORK_SIZE_LARGE) {
|
||||
} else if (ws_cfg_network_config_get(cur) == CONFIG_LARGE) {
|
||||
set_function = ws_cfg_network_size_config_set_large;
|
||||
} else {
|
||||
set_function = ws_cfg_network_size_config_set_xlarge;
|
||||
|
@ -360,6 +386,47 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1
|
|||
return CFG_SETTINGS_OK;
|
||||
}
|
||||
|
||||
cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
// Get size of the network Amount of devices in the network
|
||||
// Get the data rate of the network
|
||||
// Adjust the configuration type based on the network size and data rate
|
||||
|
||||
(void)cur;
|
||||
|
||||
ws_gen_cfg_t cfg;
|
||||
if (ws_cfg_gen_get(&cfg, NULL) < 0) {
|
||||
return CONFIG_SMALL;
|
||||
}
|
||||
ws_phy_cfg_t phy_cfg;
|
||||
if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) {
|
||||
return CONFIG_SMALL;
|
||||
}
|
||||
|
||||
uint32_t data_rate = ws_get_datarate_using_operating_mode(phy_cfg.operating_mode);
|
||||
uint8_t index;
|
||||
if (data_rate < 150000) {
|
||||
index = 0;
|
||||
} else if (data_rate < 300000) {
|
||||
index = 1;
|
||||
} else if (data_rate < 600000) {
|
||||
index = 2;
|
||||
} else {
|
||||
index = 3;
|
||||
}
|
||||
|
||||
if (cfg.network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
return CONFIG_CERTIFICATE;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_small) {
|
||||
return CONFIG_SMALL;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_medium) {
|
||||
return CONFIG_MEDIUM;
|
||||
} else if (cfg.network_size <= devices_by_datarate[index].max_for_large) {
|
||||
return CONFIG_LARGE;
|
||||
}
|
||||
return CONFIG_XLARGE;
|
||||
}
|
||||
|
||||
|
||||
static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg)
|
||||
{
|
||||
|
@ -651,6 +718,8 @@ int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg)
|
|||
cfg->regulatory_domain = REG_DOMAIN_EU;
|
||||
cfg->operating_mode = OPERATING_MODE_3;
|
||||
cfg->operating_class = 2;
|
||||
cfg->phy_mode_id = 255;
|
||||
cfg->channel_plan_id = 255;
|
||||
|
||||
return CFG_SETTINGS_OK;
|
||||
}
|
||||
|
@ -671,12 +740,16 @@ int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg)
|
|||
// Regulator domain, operating mode or class has changed
|
||||
if (cfg->regulatory_domain != new_cfg->regulatory_domain ||
|
||||
cfg->operating_mode != new_cfg->operating_mode ||
|
||||
cfg->operating_class != new_cfg->operating_class) {
|
||||
cfg->operating_class != new_cfg->operating_class ||
|
||||
cfg->phy_mode_id != new_cfg->phy_mode_id ||
|
||||
cfg->channel_plan_id != new_cfg->channel_plan_id) {
|
||||
|
||||
ws_hopping_schedule_t hopping_schdule = {
|
||||
.regulatory_domain = new_cfg->regulatory_domain,
|
||||
.operating_mode = new_cfg->operating_mode,
|
||||
.operating_class = new_cfg->operating_class
|
||||
.operating_class = new_cfg->operating_class,
|
||||
.phy_mode_id = new_cfg->phy_mode_id,
|
||||
.channel_plan_id = new_cfg->channel_plan_id
|
||||
};
|
||||
|
||||
// Check that new settings are valid
|
||||
|
@ -698,11 +771,31 @@ int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, w
|
|||
if (ret != CFG_SETTINGS_CHANGED) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Check settings and configure interface
|
||||
if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
|
||||
// Set operating mode for FSK if given with PHY mode ID
|
||||
if ((new_cfg->phy_mode_id == 1) || (new_cfg->phy_mode_id == 17)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1a;
|
||||
} else if ((new_cfg->phy_mode_id == 2) || (new_cfg->phy_mode_id == 18)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1b;
|
||||
} else if ((new_cfg->phy_mode_id == 3) || (new_cfg->phy_mode_id == 19)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2a;
|
||||
} else if ((new_cfg->phy_mode_id == 4) || (new_cfg->phy_mode_id == 20)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2b;
|
||||
} else if ((new_cfg->phy_mode_id == 5) || (new_cfg->phy_mode_id == 21)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
|
||||
} else if ((new_cfg->phy_mode_id == 6) || (new_cfg->phy_mode_id == 22)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4a;
|
||||
} else if ((new_cfg->phy_mode_id == 7) || (new_cfg->phy_mode_id == 23)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4b;
|
||||
} else if ((new_cfg->phy_mode_id == 8) || (new_cfg->phy_mode_id == 24)) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_5;
|
||||
} else {
|
||||
cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode;
|
||||
}
|
||||
cur->ws_info->hopping_schdule.phy_mode_id = new_cfg->phy_mode_id;
|
||||
cur->ws_info->hopping_schdule.channel_plan_id = new_cfg->channel_plan_id;
|
||||
cur->ws_info->hopping_schdule.regulatory_domain = new_cfg->regulatory_domain;
|
||||
cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode;
|
||||
cur->ws_info->hopping_schdule.operating_class = new_cfg->operating_class;
|
||||
|
||||
if (ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule) < 0) {
|
||||
|
|
|
@ -38,6 +38,8 @@ typedef struct ws_phy_cfg_s {
|
|||
uint8_t regulatory_domain; /**< PHY regulatory domain; default "KR" 0x09 */
|
||||
uint8_t operating_class; /**< PHY operating class; default 1 */
|
||||
uint8_t operating_mode; /**< PHY operating mode; default "1b" symbol rate 50, modulation index 1 */
|
||||
uint8_t phy_mode_id; /**< PHY mode ID; default 255 (not used) */
|
||||
uint8_t channel_plan_id; /**< Channel plan ID; default 255 (not used) */
|
||||
} ws_phy_cfg_t;
|
||||
|
||||
/**
|
||||
|
@ -146,11 +148,23 @@ typedef struct ws_cfg_s {
|
|||
#define CFG_SETTINGS_ERROR_SEC_TIMER_CONF -17 /**< Security timers configuration error */
|
||||
#define CFG_SETTINGS_ERROR_SEC_PROT_CONF -18 /**< Security protocols configuration error */
|
||||
|
||||
/** Network configuration parameters sets for different network sizes*/
|
||||
typedef enum {
|
||||
CONFIG_CERTIFICATE = 0, ///< Configuration used in Wi-SUN Certification
|
||||
CONFIG_SMALL = 1, ///< Small networks that can utilize fast recovery
|
||||
CONFIG_MEDIUM = 2, ///< Medium networks that can form quickly but require balance on load
|
||||
CONFIG_LARGE = 3, ///< Large networks that needs to throttle joining and maintenance
|
||||
CONFIG_XLARGE = 4 ///< Xlarge networks with very slow joining, maintenance and recovery profile
|
||||
} cfg_network_size_type_e;
|
||||
|
||||
|
||||
int8_t ws_cfg_settings_init(void);
|
||||
int8_t ws_cfg_settings_default_set(void);
|
||||
int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur);
|
||||
int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size);
|
||||
|
||||
cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur);
|
||||
|
||||
int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags);
|
||||
int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg);
|
||||
int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags);
|
||||
|
|
|
@ -53,33 +53,57 @@ uint8_t DEVICE_MIN_SENS = 174 - 93;
|
|||
|
||||
uint16_t test_max_child_count_override = 0xffff;
|
||||
|
||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class)
|
||||
static int8_t ws_disable_channels_in_range(uint32_t *channel_mask, uint16_t number_of_channels, uint16_t range_start, uint16_t range_stop)
|
||||
{
|
||||
uint32_t excluded_start_channel = 0xFFFFFFFF;
|
||||
uint32_t excluded_end_channel = 0xFFFFFFFF;
|
||||
|
||||
if (regulatory_domain == REG_DOMAIN_BZ) {
|
||||
if (operating_class == 1) {
|
||||
excluded_start_channel = 26;
|
||||
excluded_end_channel = 64;
|
||||
} else if (operating_class == 2) {
|
||||
excluded_start_channel = 12;
|
||||
excluded_end_channel = 32;
|
||||
} else if (operating_class == 3) {
|
||||
excluded_start_channel = 7;
|
||||
excluded_end_channel = 21;
|
||||
for (uint16_t i = 0; i < number_of_channels; i++) {
|
||||
if (i >= range_start && i <= range_stop) {
|
||||
channel_mask[0 + (i / 32)] &= ~(1 << (i % 32));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id)
|
||||
{
|
||||
// Clear channel mask
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
channel_mask[i] = 0;
|
||||
}
|
||||
|
||||
// Set channel maks outside excluded channels
|
||||
// Enable all channels
|
||||
for (uint16_t i = 0; i < number_of_channels; i++) {
|
||||
if (i < excluded_start_channel || i > excluded_end_channel) {
|
||||
channel_mask[0 + (i / 32)] |= (1 << (i % 32));
|
||||
channel_mask[0 + (i / 32)] |= (1 << (i % 32));
|
||||
}
|
||||
// Disable unsupported channels per regional frequency bands
|
||||
if (regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (channel_plan_id == 1) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7);
|
||||
} else if (channel_plan_id == 5) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 7);
|
||||
}
|
||||
}
|
||||
if (regulatory_domain == REG_DOMAIN_BZ) {
|
||||
if (channel_plan_id == 255) {
|
||||
if (operating_class == 1) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 26, 64);
|
||||
} else if (operating_class == 2) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 12, 32);
|
||||
} else if (operating_class == 3) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 7, 21);
|
||||
}
|
||||
} else {
|
||||
if (channel_plan_id == 1) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 64, 64);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 72, 103);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 106, 111);
|
||||
} else if (channel_plan_id == 2) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 24, 24);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 32, 47);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 52, 55);
|
||||
} else if (channel_plan_id == 5) {
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 10);
|
||||
ws_disable_channels_in_range(channel_mask, number_of_channels, 19, 23);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -109,6 +133,10 @@ uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
|
|||
return 400000;
|
||||
} else if (CHANNEL_SPACING_600 == channel_spacing) {
|
||||
return 600000;
|
||||
} else if (CHANNEL_SPACING_800 == channel_spacing) {
|
||||
return 800000;
|
||||
} else if (CHANNEL_SPACING_1200 == channel_spacing) {
|
||||
return 1200000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -129,6 +157,60 @@ uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id)
|
||||
{
|
||||
if (84 == phy_mode_id) {
|
||||
return 150000;
|
||||
} else if (85 == phy_mode_id) {
|
||||
return 200000;
|
||||
} else if ((68 == phy_mode_id) || (86 == phy_mode_id)) {
|
||||
return 300000;
|
||||
} else if ((34 == phy_mode_id) || (51 == phy_mode_id) || (69 == phy_mode_id)) {
|
||||
return 400000;
|
||||
} else if ((52 == phy_mode_id) || (70 == phy_mode_id)) {
|
||||
return 600000;
|
||||
} else if ((35 == phy_mode_id) || (53 == phy_mode_id)) {
|
||||
return 800000;
|
||||
} else if ((36 == phy_mode_id) || (54 == phy_mode_id)) {
|
||||
return 1200000;
|
||||
} else if (37 == phy_mode_id) {
|
||||
return 1600000;
|
||||
} else if (38 == phy_mode_id) {
|
||||
return 2400000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id)
|
||||
{
|
||||
if ((phy_mode_id >= 34) && (phy_mode_id <= 38)) {
|
||||
return OFDM_OPTION_1;
|
||||
} else if ((phy_mode_id >= 51) && (phy_mode_id <= 54)) {
|
||||
return OFDM_OPTION_2;
|
||||
} else if ((phy_mode_id >= 68) && (phy_mode_id <= 70)) {
|
||||
return OFDM_OPTION_3;
|
||||
} else if ((phy_mode_id >= 84) && (phy_mode_id <= 86)) {
|
||||
return OFDM_OPTION_4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id)
|
||||
{
|
||||
if (34 == phy_mode_id) {
|
||||
return OFDM_MCS_2;
|
||||
} else if ((35 == phy_mode_id) || (51 == phy_mode_id)) {
|
||||
return OFDM_MCS_3;
|
||||
} else if ((36 == phy_mode_id) || (52 == phy_mode_id) || (68 == phy_mode_id) || (84 == phy_mode_id)) {
|
||||
return OFDM_MCS_4;
|
||||
} else if ((37 == phy_mode_id) || (53 == phy_mode_id) || (69 == phy_mode_id) || (85 == phy_mode_id)) {
|
||||
return OFDM_MCS_5;
|
||||
} else if ((38 == phy_mode_id) || (54 == phy_mode_id) || (70 == phy_mode_id) || (86 == phy_mode_id)) {
|
||||
return OFDM_MCS_6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode)
|
||||
{
|
||||
if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
|
||||
|
@ -146,6 +228,38 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Validate PHY mode ID
|
||||
if (hopping_schdule->phy_mode_id != 255) {
|
||||
uint8_t phy_mode_id = hopping_schdule->phy_mode_id;
|
||||
uint8_t phy_type = phy_mode_id >> 4;
|
||||
uint8_t phy_mode = phy_mode_id & 0x0f;
|
||||
// Invalid PHY type
|
||||
if (phy_type > 5) {
|
||||
return -1;
|
||||
}
|
||||
// Invalid OFDM mode
|
||||
if (phy_type >= 2 && phy_mode > 6) {
|
||||
return -1;
|
||||
}
|
||||
// Skip if PHY mode is for FSK modulation
|
||||
if (!phy_mode_id || ((phy_mode_id > 8) && (phy_mode_id < 17)) || phy_mode_id > 24) {
|
||||
// Validate OFDM configurations
|
||||
if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) ||
|
||||
((phy_mode_id >= 51) && (phy_mode_id <= 54)) ||
|
||||
((phy_mode_id >= 68) && (phy_mode_id <= 70)) ||
|
||||
((phy_mode_id >= 84) && (phy_mode_id <= 86))) {
|
||||
if (ws_get_datarate_using_phy_mode_id(phy_mode_id) == 0 ||
|
||||
ws_get_ofdm_option_using_phy_mode_id(phy_mode_id) == 0 ||
|
||||
ws_get_ofdm_mcs_using_phy_mode_id(phy_mode_id) == 0) {
|
||||
//Unsupported PHY mode
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// Invalid PHY mode ID
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
hopping_schdule->channel_plan = 0;
|
||||
|
||||
if (hopping_schdule->regulatory_domain == REG_DOMAIN_KR) {
|
||||
|
@ -185,30 +299,60 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
|
|||
return -1;
|
||||
}
|
||||
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (hopping_schdule->operating_class == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->operating_class == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->operating_class == 3) {
|
||||
hopping_schdule->ch0_freq = 9026;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_600;
|
||||
if (hopping_schdule->channel_plan_id == 255) {
|
||||
if (hopping_schdule->operating_class == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->operating_class == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->operating_class == 3) {
|
||||
hopping_schdule->ch0_freq = 9026;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_600;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
if (hopping_schdule->channel_plan_id == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->channel_plan_id == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->channel_plan_id == 5) {
|
||||
hopping_schdule->ch0_freq = 9032;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_1200;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_BZ) {
|
||||
if (hopping_schdule->operating_class == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->operating_class == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->operating_class == 3) {
|
||||
hopping_schdule->ch0_freq = 9026;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_600;
|
||||
if (hopping_schdule->channel_plan_id == 255) {
|
||||
if (hopping_schdule->operating_class == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->operating_class == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->operating_class == 3) {
|
||||
hopping_schdule->ch0_freq = 9026;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_600;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
if (hopping_schdule->channel_plan_id == 1) {
|
||||
hopping_schdule->ch0_freq = 9022;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (hopping_schdule->channel_plan_id == 2) {
|
||||
hopping_schdule->ch0_freq = 9024;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (hopping_schdule->channel_plan_id == 5) {
|
||||
hopping_schdule->ch0_freq = 9032;
|
||||
hopping_schdule->channel_spacing = CHANNEL_SPACING_1200;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) {
|
||||
if (hopping_schdule->operating_class == 1) {
|
||||
|
@ -236,7 +380,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
|
|||
} else {
|
||||
return -1;
|
||||
}
|
||||
hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class);
|
||||
hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class, hopping_schdule->channel_plan_id);
|
||||
if (!hopping_schdule->number_of_channels) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -244,7 +388,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class)
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id)
|
||||
{
|
||||
if (regulatory_domain == REG_DOMAIN_KR) {
|
||||
if (operating_class == 1) {
|
||||
|
@ -269,12 +413,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
|
|||
return 10;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
} else if (operating_class == 2) {
|
||||
return 64;
|
||||
} else if (operating_class == 3) {
|
||||
return 42;
|
||||
if (channel_plan_id == 255) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
} else if (operating_class == 2) {
|
||||
return 64;
|
||||
} else if (operating_class == 3) {
|
||||
return 42;
|
||||
}
|
||||
} else {
|
||||
if (channel_plan_id == 1) {
|
||||
return 136;
|
||||
} else if (channel_plan_id == 2) {
|
||||
return 64;
|
||||
} else if (channel_plan_id == 5) {
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_JP) {
|
||||
if (operating_class == 1) {
|
||||
|
@ -285,12 +439,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat
|
|||
return 12;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_BZ) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
} else if (operating_class == 2) {
|
||||
return 64;
|
||||
} else if (operating_class == 3) {
|
||||
return 42;
|
||||
if (channel_plan_id == 255) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
} else if (operating_class == 2) {
|
||||
return 64;
|
||||
} else if (operating_class == 3) {
|
||||
return 42;
|
||||
}
|
||||
} else {
|
||||
if (channel_plan_id == 1) {
|
||||
return 136;
|
||||
} else if (channel_plan_id == 2) {
|
||||
return 64;
|
||||
} else if (channel_plan_id == 5) {
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_WW) {
|
||||
if (operating_class == 1) {
|
||||
|
@ -366,10 +530,16 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8
|
|||
}
|
||||
}
|
||||
|
||||
void ws_common_black_list_neighbour(const uint8_t *ll_address, uint8_t nd_status)
|
||||
{
|
||||
if (nd_status == ARO_FULL) {
|
||||
blacklist_update(ll_address, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
tr_warn("ARO registration Failure %s", trace_ipv6(ll_address));
|
||||
blacklist_update(ll_address, false);
|
||||
ws_bootstrap_aro_failure(cur, ll_address);
|
||||
}
|
||||
|
||||
|
@ -390,29 +560,41 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size)
|
|||
}
|
||||
}
|
||||
|
||||
static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
|
||||
static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint32_t link_lifetime)
|
||||
{
|
||||
if (link_lifetime > WS_NEIGHBOR_LINK_TIMEOUT) {
|
||||
link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
|
||||
}
|
||||
/*
|
||||
* ARO registration from child can update the link timeout so we don't need to send extra NUD if ARO received
|
||||
*/
|
||||
mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, false, false);
|
||||
|
||||
if (mac_neighbor) {
|
||||
if (mac_neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
|
||||
if (mac_neighbor->link_lifetime < link_lifetime) {
|
||||
//Set Stable timeout for temporary entry here
|
||||
if (link_lifetime > WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME && mac_neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) {
|
||||
tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index);
|
||||
}
|
||||
mac_neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
|
||||
tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index);
|
||||
|
||||
}
|
||||
//Refresh
|
||||
mac_neighbor->lifetime = mac_neighbor->link_lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
|
||||
uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint16_t aro_timeout)
|
||||
{
|
||||
uint8_t child_count = 0;
|
||||
uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size);
|
||||
|
||||
if (aro_timeout == 0) {
|
||||
//DeRegister Address Reg
|
||||
return ARO_SUCCESS;
|
||||
}
|
||||
uint32_t link_lifetime = (aro_timeout * 60) + 1;
|
||||
|
||||
// Test API to limit child count
|
||||
if (test_max_child_count_override != 0xffff) {
|
||||
max_child_count = test_max_child_count_override;
|
||||
|
@ -420,8 +602,9 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte
|
|||
|
||||
//Validate Is EUI64 already allocated for any address
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) {
|
||||
ws_common_neighbour_address_reg_link_update(interface, eui64);
|
||||
ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime);
|
||||
tr_info("Child registration from old child");
|
||||
|
||||
return ARO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -431,20 +614,21 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte
|
|||
return ARO_TOPOLOGICALLY_INCORRECT;
|
||||
}
|
||||
|
||||
|
||||
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
|
||||
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {
|
||||
child_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (child_count >= max_child_count) {
|
||||
tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
|
||||
return ARO_FULL;
|
||||
}
|
||||
|
||||
ws_common_neighbour_address_reg_link_update(interface, eui64);
|
||||
ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime);
|
||||
tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
|
||||
|
||||
return ARO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -464,21 +648,16 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con
|
|||
uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
uint32_t latency = 0;
|
||||
uint8_t network_size = cur->ws_info->cfg->gen.network_size;
|
||||
|
||||
if (network_size == NETWORK_SIZE_AUTOMATIC) {
|
||||
network_size = cur->ws_info->pan_information.pan_size / 100;
|
||||
}
|
||||
|
||||
if (network_size <= NETWORK_SIZE_SMALL) {
|
||||
// handles also NETWORK_SIZE_CERTIFICATE
|
||||
latency = 4000;
|
||||
} else if (network_size <= NETWORK_SIZE_MEDIUM) {
|
||||
latency = 8000;
|
||||
} else if (network_size <= NETWORK_SIZE_LARGE) {
|
||||
latency = 16000;
|
||||
if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) {
|
||||
// Also has the certificate settings
|
||||
latency = 5000;
|
||||
} else if (ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM) {
|
||||
latency = 10000;
|
||||
} else if (ws_cfg_network_config_get(cur) <= CONFIG_LARGE) {
|
||||
latency = 20000;
|
||||
} else {
|
||||
latency = 24000;
|
||||
latency = 30000;
|
||||
}
|
||||
|
||||
return latency;
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef struct ws_info_s {
|
|||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class);
|
||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id);
|
||||
|
||||
uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels);
|
||||
|
||||
|
@ -130,11 +130,17 @@ uint32_t ws_decode_channel_spacing(uint8_t channel_spacing);
|
|||
|
||||
uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode);
|
||||
|
||||
uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id);
|
||||
|
||||
uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id);
|
||||
|
||||
uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id);
|
||||
|
||||
phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode);
|
||||
|
||||
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule);
|
||||
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class);
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id);
|
||||
|
||||
int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur);
|
||||
|
||||
|
@ -144,11 +150,13 @@ 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);
|
||||
|
||||
void ws_common_black_list_neighbour(const uint8_t *ll_address, uint8_t nd_status);
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64);
|
||||
uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64, uint16_t aro_timeout);
|
||||
|
||||
bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64);
|
||||
|
||||
|
@ -170,10 +178,11 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size);
|
|||
#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_black_list_neighbour(ll_address, nd_status) ((void) 0)
|
||||
#define ws_common_aro_failure(cur, ll_address)
|
||||
#define ws_common_neighbor_remove(cur, ll_address)
|
||||
#define ws_common_fast_timer(cur, ticks) ((void) 0)
|
||||
#define ws_common_allow_child_registration(cur, eui64) (2)
|
||||
#define ws_common_allow_child_registration(cur, eui64, aro_timeout) (2)
|
||||
#define ws_common_negative_aro_mark(interface, eui64)(false)
|
||||
#define ws_common_latency_estimate_get(cur) 0
|
||||
#define ws_common_datarate_get(cur) 0
|
||||
|
|
|
@ -100,6 +100,8 @@ typedef struct ws_hopping_schedule_s {
|
|||
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 phy_mode_id; /**< PHY mode ID, default to 255 */
|
||||
uint8_t channel_plan_id; /**< Channel plan ID, default to 255 */
|
||||
uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */
|
||||
uint8_t uc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */
|
||||
uint8_t bc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */
|
||||
|
|
|
@ -144,9 +144,9 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
#define MPL_SMALL_K 8
|
||||
#define MPL_SMALL_SEED_LIFETIME (MPL_SMALL_IMAX * MPL_SAFE_HOP_COUNT * (MPL_SMALL_EXPIRATIONS + 1)) // time that packet should get to safe distance
|
||||
/*Medium network size*/
|
||||
#define MPL_MEDIUM_IMIN 5
|
||||
#define MPL_MEDIUM_IMAX 20
|
||||
#define MPL_MEDIUM_EXPIRATIONS 2
|
||||
#define MPL_MEDIUM_IMIN 1
|
||||
#define MPL_MEDIUM_IMAX 32
|
||||
#define MPL_MEDIUM_EXPIRATIONS 1
|
||||
#define MPL_MEDIUM_K 8
|
||||
#define MPL_MEDIUM_SEED_LIFETIME (MPL_MEDIUM_IMAX * MPL_SAFE_HOP_COUNT * (MPL_MEDIUM_EXPIRATIONS + 1)) // time that packet should get to safe distance
|
||||
/*Large network size*/
|
||||
|
@ -221,6 +221,13 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
#define WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY 5 // During discovery state how many neighbours per pan
|
||||
#define WS_PARENT_LIST_MAX_PAN_IN_ACTIVE 2 // During active state two nodes per pan is allowed
|
||||
|
||||
#define WS_CONGESTION_PACKET_SIZE 500 // Packet length for calculate how much heap message queue can fit
|
||||
#define WS_CONGESTION_QUEUE_DELAY 60 // Define message queue max length for given delay. This value is multiple by packet/seconds
|
||||
#define WS_CONGESTION_RED_DROP_PROBABILITY 10 //10.0%
|
||||
#define WS_CONGESTION_BR_MIN_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE
|
||||
#define WS_CONGESTION_BR_MAX_QUEUE_SIZE 600000 / WS_CONGESTION_PACKET_SIZE
|
||||
#define WS_CONGESTION_NODE_MIN_QUEUE_SIZE 10000 / WS_CONGESTION_PACKET_SIZE
|
||||
#define WS_CONGESTION_NODE_MAX_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE
|
||||
/*
|
||||
* Modifications for base specification.
|
||||
*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mpx_api.h"
|
||||
|
@ -80,6 +81,8 @@ int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr,
|
|||
ns_dyn_mem_free(eapol_auth_relay);
|
||||
return -1;
|
||||
}
|
||||
int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
socket_setsockopt(eapol_auth_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
|
||||
ns_list_add_to_end(&eapol_auth_relay_list, eapol_auth_relay);
|
||||
|
||||
|
|
|
@ -278,6 +278,9 @@ static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcp
|
|||
status = EAPOL_PDU_TX_OK;
|
||||
} else if (data->status == MLME_TX_NO_ACK) {
|
||||
status = EAPOL_PDU_TX_ERR_TX_NO_ACK;
|
||||
tr_error("EAPOL TX err no ack");
|
||||
} else {
|
||||
tr_error("EAPOL TX err");
|
||||
}
|
||||
msdu->tx_status(eapol_pdu_data->interface_ptr, status, msdu->tx_identifier);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mpx_api.h"
|
||||
|
@ -89,6 +90,8 @@ int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint
|
|||
ns_dyn_mem_free(eapol_relay);
|
||||
return -1;
|
||||
}
|
||||
int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
socket_setsockopt(eapol_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
|
||||
if (ws_eapol_pdu_cb_register(interface_ptr, &eapol_pdu_recv_cb_data) < 0) {
|
||||
ns_dyn_mem_free(eapol_relay);
|
||||
|
|
|
@ -68,6 +68,24 @@ int ws_management_network_name_validate(
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_phy_mode_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id)
|
||||
{
|
||||
(void)interface_id;
|
||||
(void)phy_mode_id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_channel_plan_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
(void)interface_id;
|
||||
(void)channel_plan_id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_regulatory_domain_set(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
|
|
|
@ -537,7 +537,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
|
|||
ws_llc_mpx_eapol_send(base, message);
|
||||
}
|
||||
} else {
|
||||
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) {
|
||||
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime <= WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME) {
|
||||
//Remove temp neighbour
|
||||
tr_debug("Remove Temp Entry by TX confirm");
|
||||
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor);
|
||||
|
|
|
@ -156,6 +156,74 @@ int ws_management_network_name_validate(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_phy_mode_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t phy_mode_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (interface_id >= 0 && (!cur || !ws_info(cur))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_phy_cfg_t cfg;
|
||||
ws_phy_cfg_t cfg_default;
|
||||
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_default_set(&cfg_default) < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (phy_mode_id != 255) {
|
||||
cfg.phy_mode_id = phy_mode_id;
|
||||
} else {
|
||||
cfg.phy_mode_id = cfg_default.phy_mode_id;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_channel_plan_id_set(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_plan_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (interface_id >= 0 && (!cur || !ws_info(cur))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_phy_cfg_t cfg;
|
||||
ws_phy_cfg_t cfg_default;
|
||||
if (ws_cfg_phy_get(&cfg, NULL) < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_default_set(&cfg_default) < 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (channel_plan_id != 255) {
|
||||
cfg.channel_plan_id = channel_plan_id;
|
||||
} else {
|
||||
cfg.channel_plan_id = cfg_default.channel_plan_id;
|
||||
}
|
||||
|
||||
if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_regulatory_domain_set(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
|
|
|
@ -254,7 +254,7 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *
|
|||
} else {
|
||||
|
||||
if (ws_us->channel_plan == 0) {
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class);
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class, own_shedule->channel_plan_id);
|
||||
} else if (ws_us->channel_plan == 1) {
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel;
|
||||
|
||||
|
@ -262,16 +262,16 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *
|
|||
|
||||
//Handle excluded channel and generate activate channel list
|
||||
if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) {
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
|
||||
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||
ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) {
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
|
||||
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||
ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) {
|
||||
if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) {
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id);
|
||||
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,7 @@ static int8_t ws_pae_key_storage_allocate(const void *instance, uint16_t key_sto
|
|||
if (new_storage_array == NULL) {
|
||||
key_storage_array->storage_array_handle = ns_dyn_mem_alloc(key_storage_size);
|
||||
if (!key_storage_array->storage_array_handle) {
|
||||
ns_dyn_mem_free(key_storage_array);
|
||||
return -1;
|
||||
}
|
||||
key_storage_array->allocated = true;
|
||||
|
|
|
@ -269,6 +269,8 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
|
|||
|
||||
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
|
||||
{
|
||||
(void) br_iid;
|
||||
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
if (!pae_supp) {
|
||||
return -1;
|
||||
|
@ -276,24 +278,6 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr,
|
|||
|
||||
tr_info("NW key valid indication");
|
||||
|
||||
// Store border router EUI-64 received on bootstrap complete
|
||||
memcpy(pae_supp->comp_br_eui_64, br_iid, 8);
|
||||
pae_supp->comp_br_eui_64[0] ^= 0x02;
|
||||
pae_supp->comp_br_eui_64_set = true;
|
||||
|
||||
// Get the EUI-64 used on 4WH handshake PTK generation
|
||||
uint8_t *ptk_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
|
||||
|
||||
/* If border router EUI-64 received on bootstrap complete does not match to
|
||||
EUI-64 stored with keys, delete keys */
|
||||
if (!ptk_eui_64 || memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) {
|
||||
tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s",
|
||||
ptk_eui_64 ? tr_array(ptk_eui_64, 8) : "", tr_array(pae_supp->comp_br_eui_64, 8));
|
||||
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
||||
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
||||
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
|
||||
}
|
||||
|
||||
// Stored keys are valid
|
||||
pae_supp->nw_keys_used_cnt = 0;
|
||||
|
||||
|
|
|
@ -357,6 +357,7 @@ static void icmpv6_na_wisun_aro_handler(protocol_interface_info_entry_t *cur_int
|
|||
|
||||
(void)life_time;
|
||||
if (nd_status != ARO_SUCCESS) {
|
||||
ws_common_black_list_neighbour(src_addr, nd_status);
|
||||
ws_common_aro_failure(cur_interface, src_addr);
|
||||
}
|
||||
}
|
||||
|
@ -1110,6 +1111,7 @@ buffer_t *icmpv6_up(buffer_t *buf)
|
|||
|| (buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL
|
||||
&& (buf->options.code != ICMPV6_CODE_RPL_DIO
|
||||
&& buf->options.code != ICMPV6_CODE_RPL_DIS))) {
|
||||
tr_warn("Drop: ICMP EP unsecured packet");
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
@ -1446,7 +1448,7 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status)
|
|||
ll_address[8] ^= 2;
|
||||
}
|
||||
if (rpl_control_address_register_done(buf->interface, ll_address, status)) {
|
||||
// When RPL returns true neighbor should be blacklisted
|
||||
// When RPL returns true neighbor should be deleted
|
||||
ws_common_aro_failure(buf->interface, ll_address);
|
||||
}
|
||||
}
|
||||
|
@ -1526,7 +1528,11 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
|
|||
/* If ARO Success sending is omitted, MAC ACK is used instead */
|
||||
/* Setting callback for receiving ACK from adaptation layer */
|
||||
if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) {
|
||||
buf->ack_receive_cb = icmpv6_aro_cb;
|
||||
if (aro->lifetime > 1) {
|
||||
buf->ack_receive_cb = icmpv6_aro_cb;
|
||||
} else {
|
||||
buf->ack_receive_cb = ack_receive_cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) {
|
||||
|
@ -1761,6 +1767,7 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
|
|||
tr_debug("Neighbour removed for negative response send");
|
||||
return buffer_free(buf);
|
||||
}
|
||||
buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
buf->ack_receive_cb = ack_remove_neighbour_cb;
|
||||
}
|
||||
|
||||
|
|
|
@ -1416,6 +1416,7 @@ buffer_t *ipv6_forwarding_up(buffer_t *buf)
|
|||
#endif
|
||||
default: {
|
||||
if (buf->options.ll_security_bypass_rx) {
|
||||
tr_warn("Drop: unsecured by BAD Next header %u", *nh_ptr);
|
||||
goto bad_nh;
|
||||
}
|
||||
buffer_socket_set(buf, socket_lookup_ipv6(*nh_ptr, &buf->dst_sa, &buf->src_sa, true));
|
||||
|
|
|
@ -180,7 +180,9 @@ typedef enum {
|
|||
typedef enum {
|
||||
QOS_NORMAL = 0,
|
||||
QOS_HIGH = 1,
|
||||
QOS_MAC_BEACON = 2
|
||||
QOS_NETWORK_CTRL = 2,
|
||||
QOS_EXPEDITE_FORWARD = 3,
|
||||
QOS_MAC_BEACON = 4
|
||||
} buffer_priority_t;
|
||||
|
||||
#define B_TO_MAC_MLME_MASK (B_DIR_MASK + B_FROM_MASK + B_TO_MASK )
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "ipv6_stack/ipv6_routing_table.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "6LoWPAN/lowpan_adaptation_interface.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
|
||||
#define TRACE_GROUP "mntr"
|
||||
|
@ -73,7 +74,8 @@ typedef void (ns_maintenance_gc_cb)(bool full_gc);
|
|||
*/
|
||||
static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = {
|
||||
ipv6_destination_cache_forced_gc,
|
||||
ws_pae_controller_forced_gc
|
||||
ws_pae_controller_forced_gc,
|
||||
lowpan_adaptation_free_heap
|
||||
};
|
||||
|
||||
static void ns_monitor_heap_gc(bool full_gc)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
struct cca_structure_s;
|
||||
struct buffer;
|
||||
struct mac_pre_build_frame;
|
||||
struct mac_pre_parsed_frame_s;
|
||||
struct mlme_key_descriptor_s;
|
||||
struct arm_device_driver_list;
|
||||
struct fhss_api;
|
||||
|
@ -204,6 +205,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
bool macBroadcastDisabled: 1;
|
||||
bool scan_active: 1;
|
||||
bool rf_csma_extension_supported: 1;
|
||||
bool rf_pd_ack_buffer_is_in_use: 1;
|
||||
uint16_t mac_short_address;
|
||||
uint16_t pan_id;
|
||||
uint8_t mac64[8];
|
||||
|
@ -233,7 +235,9 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
struct mac_pre_build_frame *pd_data_request_queue_to_go;
|
||||
struct mac_pre_build_frame *pd_data_request_bc_queue_to_go;
|
||||
struct mac_pre_build_frame *active_pd_data_request;
|
||||
struct mac_pre_parsed_frame_s *pd_rx_ack_buffer;
|
||||
/* MAC Beacon info */
|
||||
uint16_t allocated_ack_buffer_length;
|
||||
uint16_t max_beacon_payload_length;
|
||||
uint8_t *mac_beacon_payload;
|
||||
uint8_t mac_beacon_payload_size;
|
||||
|
@ -253,6 +257,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
|||
struct mac_pre_build_frame enhanced_ack_buffer;
|
||||
uint32_t enhanced_ack_handler_timestamp;
|
||||
arm_event_t mac_mcps_timer_event;
|
||||
arm_event_storage_t mac_ack_event;
|
||||
uint16_t indirect_pending_bytes;
|
||||
arm_nwk_mlme_event_type_e mac_mlme_event;
|
||||
mac_event_t timer_mac_event;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "mac_mcps.h"
|
||||
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
||||
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
|
||||
#include "MAC/rf_driver_storage.h"
|
||||
|
||||
#define TRACE_GROUP "mFil"
|
||||
|
||||
|
@ -291,7 +292,7 @@ int_fast8_t mac_filter_add_long(int8_t interface_id, uint8_t mac64[8], int16_t l
|
|||
return 0;
|
||||
}
|
||||
|
||||
int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_frame_t *mac_frame)
|
||||
int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_fcf_sequence_s *fcf, struct arm_pd_sap_generic_ind_s *mac_frame)
|
||||
{
|
||||
filter_instance_t *this = filter_instance_find(interface_id);
|
||||
filter_t *filter_ptr = NULL;
|
||||
|
@ -300,25 +301,24 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f
|
|||
int16_t dbm_m;
|
||||
int16_t dbm_add;
|
||||
|
||||
if (!this || !mac_frame) {
|
||||
if (!this) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!this->enabled) {
|
||||
return 0;
|
||||
}
|
||||
tr_debug_extra("mac_filter_modify_link_quality lqi %d dbm %d", mac_frame->link_quality, mac_frame->dbm);
|
||||
|
||||
tr_debug_extra("mac_filter_modify_link_quality lqi %d dbm %d", mac_frame->LQI, mac_frame->dbm);
|
||||
|
||||
if (mac_frame->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||
if (fcf->SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t srcAddress[8];
|
||||
mac_header_get_src_address(&mac_frame->fcf_dsn, mac_header_message_start_pointer(mac_frame), srcAddress);
|
||||
mac_header_get_src_address(fcf, mac_frame->data_ptr, srcAddress);
|
||||
|
||||
|
||||
//Find filter for specific address
|
||||
if (mac_frame->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_16_BIT) {
|
||||
if (fcf->SrcAddrMode == MAC_ADDR_MODE_16_BIT) {
|
||||
uint16_t mac16 = common_read_16_bit(srcAddress);
|
||||
filter_ptr = filter_find_short(this, mac16);
|
||||
if (!filter_ptr && this->resolve_long_cb) {
|
||||
|
@ -354,14 +354,14 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f
|
|||
}
|
||||
|
||||
//calculate
|
||||
int16_t lqi = ((mac_frame->LQI * lqi_m) >> 8) + lqi_add;
|
||||
int16_t lqi = ((mac_frame->link_quality * lqi_m) >> 8) + lqi_add;
|
||||
// Saturate
|
||||
if (lqi > 255) {
|
||||
mac_frame->LQI = 255;
|
||||
mac_frame->link_quality = 255;
|
||||
} else if (lqi < 0) {
|
||||
mac_frame->LQI = 0;
|
||||
mac_frame->link_quality = 0;
|
||||
} else {
|
||||
mac_frame->LQI = lqi;
|
||||
mac_frame->link_quality = lqi;
|
||||
}
|
||||
|
||||
//calculate
|
||||
|
@ -375,14 +375,14 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f
|
|||
mac_frame->dbm = dbm;
|
||||
}
|
||||
|
||||
tr_debug_extra("mac_filter_modify_link_quality result lqi %d dbm %d", mac_frame->LQI, mac_frame->dbm);
|
||||
tr_debug_extra("mac_filter_modify_link_quality result lqi %d dbm %d", mac_frame->link_quality, mac_frame->dbm);
|
||||
// If quality goes below treshold packet is dropped
|
||||
if ((dbm_m != 0x100 || dbm_add != 0) && (mac_frame->dbm < MAC_FILTER_SIGNAL_FLOOR)) {
|
||||
tr_debug_extra("Filter dropped packet signal too low");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((lqi_m != 0x100 || lqi_add != 0) && (mac_frame->LQI < 1)) {
|
||||
if ((lqi_m != 0x100 || lqi_add != 0) && (mac_frame->link_quality < 1)) {
|
||||
tr_debug_extra("Filter dropped packet LQI < 1");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#ifndef MAC_FILTER_H_
|
||||
#define MAC_FILTER_H_
|
||||
|
||||
struct mac_pre_parsed_frame_s;
|
||||
struct mac_fcf_sequence_s;
|
||||
struct arm_pd_sap_generic_ind_s;
|
||||
|
||||
/**
|
||||
* Modify the link quality values.
|
||||
|
@ -41,6 +42,6 @@ struct mac_pre_parsed_frame_s;
|
|||
* return >0 Packet is ignored.
|
||||
* return 0 Packet is not dropped.
|
||||
*/
|
||||
int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_pre_parsed_frame_s *mac_frame);
|
||||
int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_fcf_sequence_s *fcf, struct arm_pd_sap_generic_ind_s *mac_frame);
|
||||
|
||||
#endif /* MAC_FILTER_H_ */
|
||||
|
|
|
@ -2372,6 +2372,18 @@ static mac_pre_build_frame_t *mcps_sap_pd_req_queue_read(protocol_interface_rf_m
|
|||
|
||||
void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf)
|
||||
{
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->mac_class_ptr && buf->fcf_dsn.frametype == FC_ACK_FRAME) {
|
||||
struct protocol_interface_rf_mac_setup *rf_mac_setup = buf->mac_class_ptr;
|
||||
if (rf_mac_setup->rf_pd_ack_buffer_is_in_use) {
|
||||
rf_mac_setup->rf_pd_ack_buffer_is_in_use = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ns_dyn_mem_free(buf);
|
||||
}
|
||||
|
||||
|
@ -2388,6 +2400,37 @@ mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data
|
|||
return buffer;
|
||||
}
|
||||
|
||||
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_ack_buffer_get(protocol_interface_rf_mac_setup_s *rf_ptr, const uint8_t *data_ptr, uint16_t frame_length)
|
||||
{
|
||||
|
||||
if (rf_ptr->rf_pd_ack_buffer_is_in_use) {
|
||||
#ifdef __linux__
|
||||
tr_debug("mac ACK buffer get fail: already active");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (frame_length > rf_ptr->allocated_ack_buffer_length) {
|
||||
//Free Current
|
||||
if (rf_ptr->pd_rx_ack_buffer) {
|
||||
ns_dyn_mem_free(rf_ptr->pd_rx_ack_buffer);
|
||||
rf_ptr->allocated_ack_buffer_length = 0;
|
||||
}
|
||||
rf_ptr->pd_rx_ack_buffer = ns_dyn_mem_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length);
|
||||
if (!rf_ptr->pd_rx_ack_buffer) {
|
||||
return NULL;
|
||||
}
|
||||
rf_ptr->allocated_ack_buffer_length = frame_length;
|
||||
}
|
||||
memset(rf_ptr->pd_rx_ack_buffer, 0, sizeof(mac_pre_parsed_frame_t) + rf_ptr->allocated_ack_buffer_length);
|
||||
rf_ptr->pd_rx_ack_buffer->frameLength = frame_length;
|
||||
memcpy(mac_header_message_start_pointer(rf_ptr->pd_rx_ack_buffer), data_ptr, frame_length);
|
||||
//Mark active ACK buffer state
|
||||
rf_ptr->rf_pd_ack_buffer_is_in_use = true;
|
||||
return rf_ptr->pd_rx_ack_buffer;
|
||||
}
|
||||
|
||||
|
||||
static void mac_set_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type)
|
||||
{
|
||||
rf_mac_setup->active_mac_events |= (1 << event_type);
|
||||
|
@ -2458,21 +2501,36 @@ int8_t mcps_sap_pd_confirm_failure(void *mac_ptr)
|
|||
return eventOS_event_send(&event);
|
||||
}
|
||||
|
||||
void mcps_sap_pd_ack(void *ack_ptr)
|
||||
int8_t mcps_sap_pd_ack(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_parsed_frame_t *buffer)
|
||||
{
|
||||
if (mac_tasklet_event_handler < 0 || !ack_ptr) {
|
||||
return;
|
||||
if (mac_tasklet_event_handler < 0 || !buffer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->fcf_dsn.frametype == FC_ACK_FRAME) {
|
||||
arm_event_storage_t *event = &rf_ptr->mac_ack_event;
|
||||
event->data.data_ptr = buffer;
|
||||
event->data.event_data = 0;
|
||||
event->data.event_id = 0;
|
||||
event->data.event_type = MCPS_SAP_DATA_ACK_CNF_EVENT;
|
||||
event->data.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
|
||||
event->data.sender = 0;
|
||||
event->data.receiver = mac_tasklet_event_handler;
|
||||
eventOS_event_send_user_allocated(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arm_event_s event = {
|
||||
.receiver = mac_tasklet_event_handler,
|
||||
.sender = 0,
|
||||
.event_id = 0,
|
||||
.data_ptr = ack_ptr,
|
||||
.data_ptr = buffer,
|
||||
.event_type = MCPS_SAP_DATA_ACK_CNF_EVENT,
|
||||
.priority = ARM_LIB_HIGH_PRIORITY_EVENT,
|
||||
};
|
||||
|
||||
eventOS_event_send(&event);
|
||||
return eventOS_event_send(&event);
|
||||
}
|
||||
|
||||
void mcps_sap_trig_tx(void *mac_ptr)
|
||||
|
@ -2566,6 +2624,17 @@ void mac_mcps_buffer_queue_free(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
|||
mcps_sap_prebuild_frame_buffer_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (rf_mac_setup->pd_rx_ack_buffer) {
|
||||
if (rf_mac_setup->rf_pd_ack_buffer_is_in_use) {
|
||||
eventOS_cancel(&rf_mac_setup->mac_ack_event);
|
||||
rf_mac_setup->rf_pd_ack_buffer_is_in_use = false;
|
||||
}
|
||||
ns_dyn_mem_free(rf_mac_setup->pd_rx_ack_buffer);
|
||||
rf_mac_setup->pd_rx_ack_buffer = NULL;
|
||||
rf_mac_setup->allocated_ack_buffer_length = 0;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Function return list start pointer
|
||||
|
|
|
@ -36,6 +36,7 @@ struct mcps_purge_s;
|
|||
struct mcps_data_req_ie_list;
|
||||
struct channel_list_s;
|
||||
struct mcps_enhanced_frame_response_s;
|
||||
struct mac_pre_parsed_frame_s;
|
||||
|
||||
/** Address types */
|
||||
typedef enum {
|
||||
|
@ -100,6 +101,8 @@ void mcps_sap_pd_req_queue_write(struct protocol_interface_rf_mac_setup *rf_mac_
|
|||
*/
|
||||
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length);
|
||||
|
||||
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_ack_buffer_get(struct protocol_interface_rf_mac_setup *rf_ptr, const uint8_t *data_ptr, uint16_t frame_length);
|
||||
|
||||
/**
|
||||
* Forward Buffer for MAC MCPS SAP layer event handler
|
||||
*/
|
||||
|
@ -112,7 +115,7 @@ int8_t mcps_sap_pd_confirm(void *mac_ptr);
|
|||
|
||||
int8_t mcps_sap_pd_confirm_failure(void *mac_ptr);
|
||||
|
||||
void mcps_sap_pd_ack(void *ack_ptr);
|
||||
int8_t mcps_sap_pd_ack(struct protocol_interface_rf_mac_setup *rf_ptr, struct mac_pre_parsed_frame_s *buffer);
|
||||
|
||||
int8_t mac_virtual_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *message);
|
||||
|
||||
|
|
|
@ -828,6 +828,9 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
|||
tr_info("Number of channels: %u", config_params->number_of_channels);
|
||||
tr_info("Modulation: %u", config_params->modulation);
|
||||
tr_info("Modulation index: %u", config_params->modulation_index);
|
||||
tr_info("FEC: %u", config_params->fec);
|
||||
tr_info("OFDM MCS: %u", config_params->ofdm_mcs);
|
||||
tr_info("OFDM option: %u", config_params->ofdm_option);
|
||||
return 0;
|
||||
default:
|
||||
return mac_mlme_handle_set_values(rf_mac_setup, set_req);
|
||||
|
|
|
@ -480,6 +480,8 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time);
|
||||
// When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer
|
||||
if (tx_handle_retval == -1) {
|
||||
// RX channel could have changed during CSMA-CA, must update using TX done callback
|
||||
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, rf_ptr->active_pd_data_request->msduHandle);
|
||||
mac_sap_cca_fail_cb(rf_ptr, 0xffff);
|
||||
return PHY_TX_NOT_ALLOWED;
|
||||
}
|
||||
|
@ -631,14 +633,19 @@ VALIDATE_TX_TIME:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t mac_data_interface_waiting_ack(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read)
|
||||
{
|
||||
if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != fcf_read->DSN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf)
|
||||
{
|
||||
|
||||
if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
timer_mac_stop(rf_ptr);
|
||||
if (buf->fcf_dsn.framePending) {
|
||||
rf_ptr->mac_tx_result = MAC_TX_DONE_PENDING;
|
||||
|
@ -647,7 +654,9 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set
|
|||
}
|
||||
rf_ptr->macRfRadioTxActive = false;
|
||||
rf_ptr->macTxProcessActive = false;
|
||||
mcps_sap_pd_ack(buf);
|
||||
if (mcps_sap_pd_ack(rf_ptr, buf) != 0) {
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buf);
|
||||
}
|
||||
|
||||
if (rf_ptr->fhss_api) {
|
||||
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle);
|
||||
|
@ -891,22 +900,35 @@ static int8_t mac_pd_sap_generate_edfe_response(protocol_interface_rf_mac_setup_
|
|||
static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||
{
|
||||
// Unless receiving Ack, check that system has enough space to handle the new packet
|
||||
if (fcf_read->frametype != FC_ACK_FRAME) {
|
||||
if (!ns_monitor_packet_allocation_allowed()) {
|
||||
mac_pre_parsed_frame_t *buffer = NULL;
|
||||
if (fcf_read->frametype != FC_ACK_FRAME || rf_ptr->macProminousMode) {
|
||||
if (!rf_ptr->macProminousMode && !ns_monitor_packet_allocation_allowed()) {
|
||||
// stack can not handle new packets for routing
|
||||
#ifdef __linux__
|
||||
tr_debug("Packet ingress drop buffer allocation");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||
if (!buffer) {
|
||||
|
||||
buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||
if (!buffer) {
|
||||
#ifdef __linux__
|
||||
tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len);
|
||||
tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len);
|
||||
#endif
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
//Allocate ACK buffer
|
||||
buffer = mcps_sap_pre_parsed_ack_buffer_get(rf_ptr, pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||
if (!buffer) {
|
||||
#ifdef __linux__
|
||||
tr_debug("macPD ACK buffer allocate fail %u", pd_data_ind->data_len);
|
||||
#endif
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Copy Pre Parsed values
|
||||
buffer->fcf_dsn = *fcf_read;
|
||||
buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
|
||||
|
@ -1012,11 +1034,20 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
|||
mac_fcf_sequence_t fcf_read;
|
||||
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
|
||||
|
||||
buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind);
|
||||
if (buffer && mac_filter_modify_link_quality(rf_ptr->mac_interface_id, buffer) == 1) {
|
||||
// No need to send Ack - Check if RX channel needs to be updated
|
||||
if (fcf_read.ackRequested == false) {
|
||||
if (rf_ptr->fhss_api) {
|
||||
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Modify link quality
|
||||
if (mac_filter_modify_link_quality(rf_ptr->mac_interface_id, &fcf_read, pd_data_ind) == 1) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
|
||||
if (!rf_ptr->macProminousMode) {
|
||||
//Pre validate things before allocate buffer
|
||||
if (mac_pd_sap_validate_fcf(rf_ptr, &fcf_read, pd_data_ind)) {
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
|
@ -1024,12 +1055,26 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
|||
pd_data_ind->data_len = 0; // Do not update RX drop in that case
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
//Ack can be send even buffer allocate fail
|
||||
if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) {
|
||||
#ifdef __linux__
|
||||
tr_debug("Drop a Data by ignored ACK generation");
|
||||
#endif
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
if (fcf_read.frametype == FC_ACK_FRAME && mac_data_interface_waiting_ack(rf_ptr, &fcf_read)) {
|
||||
#ifdef __linux__
|
||||
tr_debug("Drop a ACK not a proper DSN");
|
||||
#endif
|
||||
goto ERROR_HANDLER;
|
||||
}
|
||||
|
||||
}
|
||||
//Allocate Buffer
|
||||
buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind);
|
||||
|
||||
if (!rf_ptr->macProminousMode) {
|
||||
|
||||
if (buffer) {
|
||||
if (mac_pd_sap_parse_length_fields(buffer, pd_data_ind, ptr)) {
|
||||
goto ERROR_HANDLER;
|
||||
|
@ -1098,7 +1143,7 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
|||
//Mark session closed
|
||||
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||
rf_ptr->mac_edfe_tx_active = false;
|
||||
if (mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) {
|
||||
if (mac_data_interface_waiting_ack(rf_ptr, &buffer->fcf_dsn) || mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) {
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buffer);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -406,6 +406,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do
|
|||
uint16_t ip_len = buffer_data_length(buf);
|
||||
|
||||
while (mpl_total_buffered + ip_len > MAX_BUFFERED_MESSAGES_SIZE) {
|
||||
tr_debug("MPL MAX buffered message size limit...free space");
|
||||
mpl_free_space();
|
||||
}
|
||||
|
||||
|
@ -427,6 +428,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do
|
|||
|
||||
mpl_buffered_message_t *message = ns_dyn_mem_alloc(sizeof(mpl_buffered_message_t) + ip_len);
|
||||
if (!message) {
|
||||
tr_debug("No heap for new MPL message");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(message->message, buffer_data_pointer(buf), ip_len);
|
||||
|
@ -475,6 +477,7 @@ static void mpl_buffer_transmit(mpl_domain_t *domain, mpl_buffered_message_t *me
|
|||
uint16_t ip_len = mpl_buffer_size(message);
|
||||
buffer_t *buf = buffer_get(ip_len);
|
||||
if (!buf) {
|
||||
tr_debug("No heap for MPL transmit");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -939,6 +942,9 @@ bool mpl_forwarder_process_message(buffer_t *buf, mpl_domain_t *domain, bool see
|
|||
}
|
||||
|
||||
message = mpl_buffer_create(buf, domain, seed, sequence, hop_limit);
|
||||
if (!message) {
|
||||
tr_debug("MPL Buffer Craete fail");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct arm_device_driver_list;
|
|||
struct mlme_security_s;
|
||||
struct load_balance_api;
|
||||
struct nwk_wpan_nvm_api;
|
||||
struct red_info_s;
|
||||
|
||||
#define SLEEP_MODE_REQ 0x80
|
||||
#define SLEEP_PERIOD_ACTIVE 0x40
|
||||
|
@ -445,6 +446,7 @@ struct protocol_interface_info_entry {
|
|||
struct auth_info *pana_sec_info_temp;
|
||||
br_info_t *border_router_setup;
|
||||
struct load_balance_api *lb_api;
|
||||
struct red_info_s *random_early_detection;
|
||||
neigh_cache_s neigh_cache;
|
||||
pan_blaclist_cache_s pan_blaclist_cache;
|
||||
pan_coordinator_blaclist_cache_s pan_cordinator_black_list;
|
||||
|
|
|
@ -44,7 +44,8 @@ typedef enum {
|
|||
STATS_BUFFER_HEADROOM_FAIL,
|
||||
STATS_ETX_1ST_PARENT,
|
||||
STATS_ETX_2ND_PARENT,
|
||||
STATS_AL_TX_QUEUE_SIZE
|
||||
STATS_AL_TX_QUEUE_SIZE,
|
||||
STATS_AL_TX_CONGESTION_DROP
|
||||
|
||||
} nwk_stats_type_t;
|
||||
|
||||
|
|
|
@ -152,6 +152,9 @@ void protocol_stats_update(nwk_stats_type_t type, uint16_t update_val)
|
|||
nwk_stats_ptr->adapt_layer_tx_queue_peak = nwk_stats_ptr->adapt_layer_tx_queue_size;
|
||||
}
|
||||
break;
|
||||
case STATS_AL_TX_CONGESTION_DROP:
|
||||
nwk_stats_ptr->adapt_layer_tx_congestion_drop++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "NWK_INTERFACE/Include/protocol_stats.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "ipv6_stack/protocol_ipv6.h"
|
||||
#include "Service_Libs/etx/etx.h" /* slight ick */
|
||||
|
||||
|
@ -1168,6 +1169,23 @@ malformed:
|
|||
goto invalid_parent;
|
||||
}
|
||||
|
||||
/* RFC 6550 8.3: A DIO from a sender with lesser DAGRank that causes no
|
||||
* changes to the recipient's parent set, preferred parent, or Rank SHOULD
|
||||
* be considered consistent with respect to the Trickle timer.
|
||||
*
|
||||
* Now, if we don't run parent selection immediately, how do we know if it's
|
||||
* consistent or not? Compromise is to treat all lower ranked DIOs as
|
||||
* consistent, and reset (and hold) the consistent counter to 0 if any of
|
||||
* the above change. This actually seems better than the RFC 6550 rule, as
|
||||
* it guarantees we will transmit if those change. The rule as stated
|
||||
* would mean a large number of parent messages would stop us advertising
|
||||
* a Rank change.
|
||||
*/
|
||||
if (version == rpl_instance_current_dodag_version(instance) &&
|
||||
(rpl_rank_compare(dodag, rank, rpl_instance_current_rank(instance)) & RPL_CMP_LESS)) {
|
||||
rpl_instance_consistent_rx(instance);
|
||||
}
|
||||
|
||||
/* Now we create the neighbour, if we don't already have a record */
|
||||
if (!neighbour) {
|
||||
|
||||
|
@ -1207,23 +1225,6 @@ malformed:
|
|||
rpl_dodag_set_leaf(dodag, true);
|
||||
}
|
||||
|
||||
/* RFC 6550 8.3: A DIO from a sender with lesser DAGRank that causes no
|
||||
* changes to the recipient's parent set, preferred parent, or Rank SHOULD
|
||||
* be considered consistent with respect to the Trickle timer.
|
||||
*
|
||||
* Now, if we don't run parent selection immediately, how do we know if it's
|
||||
* consistent or not? Compromise is to treat all lower ranked DIOs as
|
||||
* consistent, and reset (and hold) the consistent counter to 0 if any of
|
||||
* the above change. This actually seems better than the RFC 6550 rule, as
|
||||
* it guarantees we will transmit if those change. The rule as stated
|
||||
* would mean a large number of parent messages would stop us advertising
|
||||
* a Rank change.
|
||||
*/
|
||||
if (version == rpl_instance_current_dodag_version(instance) &&
|
||||
(rpl_rank_compare(dodag, rank, rpl_instance_current_rank(instance)) & RPL_CMP_LESS)) {
|
||||
rpl_instance_consistent_rx(instance);
|
||||
}
|
||||
|
||||
rpl_instance_neighbours_changed(instance, dodag);
|
||||
|
||||
return buffer_free(buf);
|
||||
|
@ -1292,6 +1293,10 @@ void rpl_control_transmit(rpl_domain_t *domain, protocol_interface_info_entry_t
|
|||
/* Others set "0", which means use interface default */
|
||||
buf->options.hop_limit = addr_ipv6_scope(buf->dst_sa.address, cur) <= IPV6_SCOPE_LINK_LOCAL ? 255 : 0;
|
||||
|
||||
if (code == ICMPV6_CODE_RPL_DAO || code == ICMPV6_CODE_RPL_DAO_ACK || buf->dst_sa.address[0] != 0xff) {
|
||||
//DAO and DAO ACK and unicast traffic with Higher priority
|
||||
buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
}
|
||||
|
||||
if (dst == NULL && cur == NULL) {
|
||||
rpl_control_transmit_all_interfaces(domain, buf);
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "ipv6_stack/ipv6_routing_table.h"
|
||||
#include "Common_Protocols/ip.h"
|
||||
|
||||
#include "net_rpl.h"
|
||||
#include "RPL/rpl_protocol.h"
|
||||
|
@ -884,9 +885,24 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance)
|
|||
instance->requested_dao_ack = need_ack;
|
||||
instance->dao_in_transit = true;
|
||||
if (instance->dao_attempt < 16) {
|
||||
uint32_t t = (uint32_t) rpl_policy_initial_dao_ack_wait(instance->domain, mop) << instance->dao_attempt;
|
||||
t = randLIB_randomise_base(t, 0x4000, 0xC000);
|
||||
instance->dao_retry_timer = t <= 0xffff ? t : 0xffff;
|
||||
|
||||
uint32_t delay = rpl_policy_initial_dao_ack_wait(instance->domain, mop);
|
||||
if (delay < dodag->dio_timer_params.Imin) {
|
||||
//Use Imin Based on delay if it is longer than cache retry
|
||||
delay = dodag->dio_timer_params.Imin;
|
||||
}
|
||||
//Multiply Delay by attempt
|
||||
delay = delay << instance->dao_attempt;
|
||||
|
||||
if (delay > 5400) {
|
||||
//MAX base 540 seconds (9min)
|
||||
delay = 5400;
|
||||
}
|
||||
|
||||
// 0.5 - 1.5 *t randomized base delay
|
||||
delay = randLIB_randomise_base(delay, 0x4000, 0xC000);
|
||||
|
||||
instance->dao_retry_timer = delay;
|
||||
} else {
|
||||
instance->dao_retry_timer = 0xffff;
|
||||
}
|
||||
|
@ -1874,6 +1890,7 @@ static bool rpl_instance_push_address_registration(protocol_interface_info_entry
|
|||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
tr_info("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address));
|
||||
protocol_push(buf);
|
||||
return true;
|
||||
|
|
|
@ -180,6 +180,7 @@ struct rpl_instance {
|
|||
bool requested_dao_ack: 1; /* If we requested an ACK (so we retry if no ACK, rather than assuming success) */
|
||||
bool pending_neighbour_confirmation: 1; /* if we have not finished address registration state to parent */
|
||||
bool parent_was_selected: 1;
|
||||
bool advertised_dodag_membership_since_last_repair: 1; /* advertised dodag membership since last repair */
|
||||
uint8_t poison_count;
|
||||
uint8_t repair_dis_count;
|
||||
uint16_t repair_dis_timer;
|
||||
|
@ -192,7 +193,7 @@ struct rpl_instance {
|
|||
rpl_dodag_version_t *current_dodag_version; /* Pointer to DODAG version we are a member of (if any) */
|
||||
uint16_t current_rank; /* Current rank in current DODAG Version */
|
||||
uint16_t parent_selection_timer;
|
||||
rpl_dodag_version_t *last_advertised_dodag_version; /* Pointer to last DODAG version we advertised */
|
||||
|
||||
trickle_t dio_timer; /* Trickle timer for DIO transmission */
|
||||
rpl_dao_root_transit_children_list_t root_children;
|
||||
rpl_dao_target_list_t dao_targets; /* List of DAO targets */
|
||||
|
|
|
@ -1665,8 +1665,9 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_
|
|||
#endif
|
||||
}
|
||||
rpl_dodag_version_limit_greediness(dodag_version, rank);
|
||||
|
||||
instance->last_advertised_dodag_version = dodag_version;
|
||||
if (rank != RPL_RANK_INFINITE) {
|
||||
instance->advertised_dodag_membership_since_last_repair = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void rpl_instance_dis_timer(rpl_instance_t *instance, uint16_t seconds)
|
||||
|
@ -1715,6 +1716,7 @@ void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair)
|
|||
instance->repair_dis_count = 0;
|
||||
} else {
|
||||
instance->repair_dis_timer = 0;
|
||||
instance->advertised_dodag_membership_since_last_repair = false;
|
||||
}
|
||||
|
||||
/* When repair ends, eliminate all higher-rank neighbours (potential sub-DODAG) from table */
|
||||
|
@ -1839,8 +1841,14 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks)
|
|||
|
||||
/* Delay sending first DIO if we are still potentially gathering info */
|
||||
/* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */
|
||||
if (!rpl_instance_am_root(instance) && !instance->last_advertised_dodag_version && rpl_policy_parent_confirmation_requested()) {
|
||||
// We dont have any valid parent selected
|
||||
if (!rpl_instance_am_root(instance) && !instance->poison_count && !instance->advertised_dodag_membership_since_last_repair && rpl_policy_parent_confirmation_requested()) {
|
||||
|
||||
// We don't have DAO target generated
|
||||
if (ns_list_count(&instance->dao_targets) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't have any valid parent selected
|
||||
if (!rpl_instance_parent_selection_ready(instance)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -652,6 +652,14 @@ static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t
|
|||
radius_msg_length += AVP_TYPE_NAS_IPV6_ADDRESS_LEN;
|
||||
|
||||
uint8_t *radius_msg_ptr = ns_dyn_mem_temporary_alloc(radius_msg_length);
|
||||
if (radius_msg_ptr == NULL) {
|
||||
if (data->send_radius_msg != NULL) {
|
||||
ns_dyn_mem_free(data->send_radius_msg);
|
||||
}
|
||||
data->send_radius_msg = NULL;
|
||||
data->send_radius_msg_len = 0;
|
||||
return;
|
||||
}
|
||||
uint8_t *radius_msg_start_ptr = radius_msg_ptr;
|
||||
|
||||
*radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code
|
||||
|
|
|
@ -416,7 +416,7 @@ static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int l
|
|||
|
||||
int8_t tls_sec_prot_lib_process(tls_security_t *sec)
|
||||
{
|
||||
int ret = -1;
|
||||
int32_t ret = -1;
|
||||
|
||||
while (ret != MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
ret = mbedtls_ssl_handshake_step(&sec->ssl);
|
||||
|
@ -428,6 +428,7 @@ int8_t tls_sec_prot_lib_process(tls_security_t *sec)
|
|||
#endif
|
||||
|
||||
if (ret && (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
|
||||
tr_error("TLS error: %" PRId32, ret);
|
||||
return TLS_SEC_PROT_LIB_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ struct fhss_structure {
|
|||
uint8_t active_fhss_events;
|
||||
uint16_t number_of_channels;
|
||||
uint16_t number_of_uc_channels;
|
||||
uint16_t number_of_bc_channels;
|
||||
uint16_t optimal_packet_length;
|
||||
fhss_states fhss_state;
|
||||
uint32_t fhss_timeout;
|
||||
|
|
|
@ -195,7 +195,7 @@ void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure)
|
|||
if (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval == 0 || fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval == 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS;
|
||||
uint32_t txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MAX;
|
||||
if (fhss_structure->callbacks.read_datarate) {
|
||||
/* Calculate minimum TX slot length which can fit optimal packet length twice.
|
||||
* Twice, because 0, 1, 4, 5... hop starts transmission at the beginning of TX slot and 2, 3, 6, 7... hop at the middle of TX slot
|
||||
|
@ -217,9 +217,14 @@ void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure)
|
|||
if (datarate) {
|
||||
txrx_slot_length_ms_tmp = ((fhss_structure->optimal_packet_length * 2) * (8000000 / datarate)) / 1000;
|
||||
// Do not allow using too high TX slot length.
|
||||
if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS) {
|
||||
tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS);
|
||||
txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS;
|
||||
if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS_MAX) {
|
||||
tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS_MAX);
|
||||
txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MAX;
|
||||
}
|
||||
// Do not allow using too low TX slot length.
|
||||
if (txrx_slot_length_ms_tmp < WS_TXRX_SLOT_LEN_MS_MIN) {
|
||||
tr_debug("TX slot length setting too low %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS_MIN);
|
||||
txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,14 +246,14 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure)
|
|||
int32_t next_channel = fhss_structure->ws->fhss_configuration.broadcast_fixed_channel;
|
||||
|
||||
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
|
||||
next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels, NULL);
|
||||
next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_bc_channels, NULL);
|
||||
next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||
if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_channels) {
|
||||
if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_bc_channels) {
|
||||
fhss_structure->ws->bc_slot = 0;
|
||||
}
|
||||
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_DH1CF) {
|
||||
fhss_structure->ws->bc_slot++;
|
||||
next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels);
|
||||
next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_bc_channels);
|
||||
next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_VENDOR_DEF_CF) {
|
||||
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
||||
|
@ -338,7 +343,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
|||
}
|
||||
|
||||
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
|
||||
fhss_structure->ws->bc_slot %= fhss_structure->number_of_channels;
|
||||
fhss_structure->ws->bc_slot %= fhss_structure->number_of_bc_channels;
|
||||
}
|
||||
|
||||
if (fhss_structure->ws->is_on_bc_channel == false) {
|
||||
|
@ -604,9 +609,14 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a
|
|||
if (!fhss_structure) {
|
||||
return -1;
|
||||
}
|
||||
if (is_broadcast_addr) {
|
||||
// Allow broadcast destination on broadcast channel
|
||||
if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) {
|
||||
return 0;
|
||||
}
|
||||
// Do not allow broadcast destination on unicast channel
|
||||
if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == false)) {
|
||||
return -3;
|
||||
}
|
||||
// Do not allow unicast destination on broadcast channel
|
||||
if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) {
|
||||
return -1;
|
||||
|
@ -919,7 +929,7 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t
|
|||
uint32_t cur_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
||||
uint32_t tx_trig_offset_us = (txrx_slot_length_us / 2) * calc_own_tx_trig_slot(fhss_structure->own_hop);
|
||||
|
||||
uint32_t next_tx_trig_slot_start_us = unicast_start_us + (txrx_slot_length_us * !fhss_ws_check_tx_allowed(fhss_structure)) + tx_trig_offset_us;
|
||||
uint32_t next_tx_trig_slot_start_us = unicast_start_us + (txrx_slot_length_us * (fhss_structure->own_hop & 1)) + tx_trig_offset_us;
|
||||
uint32_t next_tx_trig_slot_end_us = next_tx_trig_slot_start_us + (txrx_slot_length_us / 2);
|
||||
while ((next_tx_trig_slot_start_us < cur_time_us) || ((next_tx_trig_slot_start_us - cur_time_us) > (uint32_t) MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval))) {
|
||||
if (cur_time_us < next_tx_trig_slot_end_us) {
|
||||
|
@ -1076,13 +1086,13 @@ int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[
|
|||
|
||||
int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration)
|
||||
{
|
||||
int channel_count = channel_list_count_channels(fhss_configuration->channel_mask);
|
||||
int channel_count_bc = channel_list_count_channels(fhss_configuration->channel_mask);
|
||||
int channel_count_uc = channel_list_count_channels(fhss_configuration->unicast_channel_mask);
|
||||
if (channel_count <= 0) {
|
||||
if (channel_count_bc <= 0 || fhss_configuration->channel_mask_size == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fhss_structure->number_of_channels < channel_count ||
|
||||
if (fhss_structure->number_of_bc_channels < channel_count_bc ||
|
||||
(channel_count_uc && fhss_structure->number_of_uc_channels < channel_count_uc)) {
|
||||
// Channel amount changed to largeneed to reallocate channel table
|
||||
ns_dyn_mem_free(fhss_structure->ws->tr51_channel_table);
|
||||
|
@ -1090,7 +1100,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
|
|||
ns_dyn_mem_free(fhss_structure->ws->tr51_output_table);
|
||||
fhss_structure->ws->tr51_output_table = NULL;
|
||||
|
||||
if (fhss_ws_manage_channel_table_allocation(fhss_structure, channel_count_uc > channel_count ? channel_count_uc : channel_count)) {
|
||||
if (fhss_ws_manage_channel_table_allocation(fhss_structure, channel_count_uc > channel_count_bc ? channel_count_uc : channel_count_bc)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1113,10 +1123,11 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
|
|||
for (uint8_t i = 0; i < 8; i++) {
|
||||
fhss_structure->ws->fhss_configuration.unicast_channel_mask[i] = fhss_configuration->channel_mask[i];
|
||||
}
|
||||
channel_count_uc = channel_count;
|
||||
channel_count_uc = channel_count_bc;
|
||||
}
|
||||
|
||||
fhss_structure->number_of_channels = channel_count;
|
||||
fhss_structure->number_of_channels = fhss_configuration->channel_mask_size;
|
||||
fhss_structure->number_of_bc_channels = channel_count_bc;
|
||||
fhss_structure->number_of_uc_channels = channel_count_uc;
|
||||
if (fhss_configuration->ws_uc_channel_function == WS_FIXED_CHANNEL) {
|
||||
fhss_structure->rx_channel = fhss_configuration->unicast_fixed_channel;
|
||||
|
@ -1127,7 +1138,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
|
|||
fhss_structure->ws->fhss_configuration.broadcast_fixed_channel,
|
||||
fhss_structure->ws->fhss_configuration.ws_uc_channel_function,
|
||||
fhss_structure->ws->fhss_configuration.ws_bc_channel_function,
|
||||
fhss_structure->number_of_channels,
|
||||
fhss_structure->number_of_bc_channels,
|
||||
fhss_structure->number_of_uc_channels,
|
||||
fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval,
|
||||
fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval,
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
|
||||
// TX slot length is optimised to this packet length
|
||||
#define OPTIMAL_PACKET_LENGTH 500
|
||||
// Default TX/RX slot length in milliseconds. Is used when datarate is not given by PHY.
|
||||
#define WS_TXRX_SLOT_LEN_MS 100
|
||||
// Max TX/RX slot length in milliseconds. Is used when datarate is not given by PHY or calculated slot length exceeds maximum allowed.
|
||||
#define WS_TXRX_SLOT_LEN_MS_MAX 100
|
||||
// Min TX/RX slot length in milliseconds. Is used when calculated slot length is under minimum allowed.
|
||||
#define WS_TXRX_SLOT_LEN_MS_MIN 10
|
||||
// Default minimum broadcast synchronization interval in seconds
|
||||
#define DEFAULT_MIN_SYNCH_INTERVAL 60
|
||||
// Drift compensation allowed if at least SYNCH_COMPENSATION_MIN_INTERVAL (seconds) since last synchronization
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "randLIB.h"
|
||||
#include "Service_Libs/random_early_detection/random_early_detection.h"
|
||||
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
|
||||
|
||||
|
||||
red_info_t *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_max_p, uint16_t weight)
|
||||
{
|
||||
//Weight must be between 1-256
|
||||
if (weight == 0 || weight > 256) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Probability must be between 1-100
|
||||
if (drop_max_p == 0 || drop_max_p > 100) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Max Threshold can't smaller or similar than min
|
||||
if (threshold_max <= threshold_min) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
red_info_t *red_info = ns_dyn_mem_alloc(sizeof(red_info_t));
|
||||
if (red_info) {
|
||||
red_info->count = 0;
|
||||
red_info->averageQ = 0;
|
||||
red_info->parameters.drop_maX_P = drop_max_p;
|
||||
red_info->parameters.threshold_max = threshold_max;
|
||||
red_info->parameters.threshold_min = threshold_min;
|
||||
red_info->parameters.weight = weight;
|
||||
}
|
||||
|
||||
return red_info;
|
||||
}
|
||||
|
||||
|
||||
void random_early_detection_free(struct red_info_s *red_info)
|
||||
{
|
||||
ns_dyn_mem_free(red_info);
|
||||
}
|
||||
|
||||
//calculate average and return averaged value back
|
||||
uint16_t random_early_detetction_aq_calc(red_info_t *red_info, uint16_t sampleLen)
|
||||
{
|
||||
if (!red_info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (red_info->parameters.weight == RED_AVERAGE_WEIGHT_DISABLED || red_info->averageQ == 0) {
|
||||
red_info->averageQ = sampleLen * 256;
|
||||
return sampleLen;
|
||||
}
|
||||
|
||||
// AQ = (1-weight) * average_queue + weight*sampleLen
|
||||
// Now Sample is scaled by 256 which is not loosing so much tail at average
|
||||
|
||||
//Weight Last Average part (1-weight) * average_queue with scaled 256
|
||||
uint32_t averageSum = ((256 - red_info->parameters.weight) * red_info->averageQ) / 256;
|
||||
//Add new weighted sample lenght (weight*sampleLen)
|
||||
averageSum += (red_info->parameters.weight * sampleLen);
|
||||
|
||||
if (averageSum & 1) {
|
||||
//If sum is ODD add 1 this will help to not stuck like 1,99 average to -> 2
|
||||
averageSum++;
|
||||
}
|
||||
//Store new average
|
||||
red_info->averageQ = averageSum;
|
||||
//Return always same format scaled than inn
|
||||
return red_info->averageQ / 256;
|
||||
|
||||
}
|
||||
|
||||
uint16_t random_early_detetction_aq_read(red_info_t *red_info)
|
||||
{
|
||||
if (!red_info) {
|
||||
return 0;
|
||||
}
|
||||
return red_info->averageQ / 256;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool random_early_detection_congestion_check(red_info_t *red_info)
|
||||
{
|
||||
if (!red_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Calulate Average queue size
|
||||
uint16_t sampleLen = red_info->averageQ / 256;;
|
||||
|
||||
if (sampleLen <= red_info->parameters.threshold_min) {
|
||||
//Can be added to queue without any RED operation
|
||||
red_info->count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sampleLen > red_info->parameters.threshold_max) {
|
||||
//Always drop over threshold_max
|
||||
red_info->count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate probability for packet drop
|
||||
// tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min);
|
||||
uint32_t tempP = (uint32_t) red_info->parameters.drop_maX_P * PROB_SCALE
|
||||
* (sampleLen - red_info->parameters.threshold_min)
|
||||
/ (red_info->parameters.threshold_max - red_info->parameters.threshold_min);
|
||||
|
||||
// Next Prob = tempP / (1 - count*tempP)
|
||||
// This will increase probability and
|
||||
|
||||
//Calculate first divider part
|
||||
uint32_t Prob = red_info->count * tempP;
|
||||
|
||||
//Check that divider it is not >= 0
|
||||
if (Prob >= PROB_SCALE_MAX) {
|
||||
|
||||
red_info->count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Calculate only when count * tempP is smaller than scaler
|
||||
Prob = (tempP * PROB_SCALE_MAX) / (PROB_SCALE_MAX - Prob);
|
||||
if (Prob > randLIB_get_random_in_range(0, PROX_MAX_RANDOM)) {
|
||||
//Drop packet
|
||||
red_info->count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Increment count next round check
|
||||
red_info->count++;
|
||||
return false;
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_
|
||||
#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//This value cant be bigger than 655
|
||||
#define PROB_SCALE 512
|
||||
#define PROB_SCALE_MAX PROB_SCALE * 100
|
||||
#define PROX_MAX_RANDOM PROB_SCALE_MAX-1
|
||||
|
||||
typedef struct red_config_s {
|
||||
uint16_t weight; /*< Weight for new sample len, 256 disabled average */
|
||||
uint16_t threshold_min; /*< Threshold Min value which start possibility start drop a packet */
|
||||
uint16_t threshold_max; /*< Threshold Max this value give max Probability for configured value over that every new packet will be dropped*/
|
||||
uint8_t drop_maX_P; /*< Max probability for drop packet between threshold_min and threshold_max threshold */
|
||||
} red_config_t;
|
||||
|
||||
typedef struct red_info_s {
|
||||
red_config_t parameters; /*< Random Early detetction parameters for queue avarge and packet drop */
|
||||
uint32_t averageQ; /*< Average queue size Scaled by 256 1.0 is 256 */
|
||||
uint16_t count; /*< Missed Packet drop's. This value is incremented when average queue is over min threshoild and packet is noot dropped */
|
||||
} red_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ */
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_
|
||||
#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct red_info_s;
|
||||
|
||||
#define RED_AVERAGE_WEIGHT_DISABLED 256 /*< Average is disabled */
|
||||
#define RED_AVERAGE_WEIGHT_HALF 128 /*< Average weight for new sample is 0.5*new + 0.5 to last one */
|
||||
#define RED_AVERAGE_WEIGHT_QUARTER 64 /*< Average weight for new sample is 1/4 + 3/4 to last one */
|
||||
#define RED_AVERAGE_WEIGHT_EIGHTH 32 /*< Average weight for new sample is 1/8 + 7/8 to last one */
|
||||
|
||||
/**
|
||||
* \brief Create Random early detection data
|
||||
*
|
||||
* Function will config parameters how wide are Random Early detection drop will work.
|
||||
*
|
||||
* How to use parameters:
|
||||
*
|
||||
* Weight is definition how message queue Average (AQ) is calculated. Smaller weight will give smoother AQ update.
|
||||
*
|
||||
* AQ = (1-weight) * average_queue + weight*sampleLen;
|
||||
*
|
||||
* * RED_AVERAGE_WEIGHT_DISABLED disable Average by max weight to new sample length
|
||||
* * RED_AVERAGE_WEIGHT_HALF last average*0.5 + 0.5*new sample: Smooth Average light packet filter
|
||||
* * RED_AVERAGE_WEIGHT_QUARTER last average*0.75 + 0.25*new sample: Medium packet burst filtering
|
||||
* * RED_AVERAGE_WEIGHT_EIGHTH last average*7/8 + 1/8*new sample: Good for filtering packet burst and big networks
|
||||
*
|
||||
* How to configure packet drop possibility:
|
||||
*
|
||||
* Define base Probability based current AQ, average length
|
||||
*
|
||||
* tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min);
|
||||
*
|
||||
* Prob = tempP / (1 - count*tempP)
|
||||
*
|
||||
* threshold_min and threshold_max threshold define area for random early detection drop. When Average queue size go over Min threshold packet may drop by given maxProbability.
|
||||
* System will work smoother if min -max threshold range is wide. Then random drop is may cover small data burst until Max threshold Avarage is reached.
|
||||
* After Max every new packet will be dropped.
|
||||
*
|
||||
* Config Examples.
|
||||
*
|
||||
* Threshold values must be set how much device can buffer data.
|
||||
*
|
||||
* Small size data buffering:
|
||||
* random_early_detection_create(32, 96, 10, RED_AVERAGE_WEIGHT_QUARTER)
|
||||
*
|
||||
* Medium size data buffering:
|
||||
* random_early_detection_create(96, 256, 10, RED_AVERAGE_WEIGHT_EIGHTH)
|
||||
*
|
||||
* High size buffering:
|
||||
* random_early_detection_create(256, 600, 10, RED_AVERAGE_WEIGHT_EIGHTH)
|
||||
*
|
||||
* \param threshold_min min average queue size which enable packet drop
|
||||
* \param threshold_max average queue size when all new packets start drop
|
||||
* \param drop_maX_P is percent probability to drop packet 100-1 are possible values
|
||||
* \param weight accepted values 256-1, 256 is 1.0 weight which mean that new queue size overwrite old. 128 is 0.5 which gives 0.5 from old + 0.5 from new.
|
||||
* \return Pointer for allocated structure, NULL if memory allocation fail
|
||||
*/
|
||||
struct red_info_s *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_maX_P, uint16_t weight);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Free Random early detection data
|
||||
*
|
||||
*
|
||||
* \param red_info pointer to data
|
||||
*/
|
||||
void random_early_detection_free(struct red_info_s *red_info);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Random early detection drop function
|
||||
*
|
||||
* \param red_info pointer, which is created user include all configurations
|
||||
* \param sampleLen Current queue length
|
||||
* \return true Drop packet
|
||||
* \return false Packet can be added to queue
|
||||
*/
|
||||
bool random_early_detection_congestion_check(struct red_info_s *red_info);
|
||||
|
||||
/**
|
||||
* \brief Random early detection Average queue calculate
|
||||
*
|
||||
* Call this when add or remove from queue
|
||||
*
|
||||
* \param red_info pointer, which is created user include all configurations
|
||||
* \param sampleLen Current queue length
|
||||
*
|
||||
* \return New average
|
||||
*/
|
||||
uint16_t random_early_detetction_aq_calc(struct red_info_s *red_info, uint16_t sampleLen);
|
||||
|
||||
/**
|
||||
* \brief Read Random early detection Average queue size
|
||||
*
|
||||
* Call this when add or remove from queue
|
||||
*
|
||||
* \param red_info pointer, which is created user include all configurations
|
||||
*
|
||||
* \return Current average
|
||||
*/
|
||||
uint16_t random_early_detetction_aq_read(struct red_info_s *red_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ */
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
|
||||
#include "eventOS_event.h"
|
||||
#include "Core/include/ns_monitor.h"
|
||||
#include "mac_api.h" // for mcps_packet_ingress_rate_limit_by_memory
|
||||
#include "MAC/IEEE802_15_4/mac_mcps_sap.h" // for mcps_packet_ingress_rate_limit_by_memory
|
||||
|
|
|
@ -29,9 +29,10 @@
|
|||
#include "socket_api.h"
|
||||
#include "net_interface.h"
|
||||
#include "common_functions.h"
|
||||
|
||||
#include "libDHCPv6/libDHCPv6.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h" // just for protocol_core_monotonic_time
|
||||
|
||||
#include "Common_Protocols/ip.h"
|
||||
#include "dhcp_service_api.h"
|
||||
#ifdef HAVE_DHCPV6
|
||||
#define TRACE_GROUP "dhcp"
|
||||
|
@ -437,7 +438,7 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
uint8_t *ptr = msg_iov[1].iov_base;
|
||||
uint8_t msg_type = *ptr;
|
||||
|
||||
|
||||
int16_t tc = 0;
|
||||
if (msg_type == DHCPV6_RELAY_FORWARD) {
|
||||
tr_error("Drop not supported DHCPv6 forward at Agent");
|
||||
goto cleanup;
|
||||
|
@ -497,7 +498,10 @@ void recv_dhcp_relay_msg(void *cb_res)
|
|||
msg_iov[0].iov_len = 38;
|
||||
msg_iov[1].iov_len = msg_len;
|
||||
tr_debug("Forward Client msg to server");
|
||||
tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
|
||||
}
|
||||
socket_setsockopt(sckt_data->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
|
||||
cleanup:
|
||||
ns_dyn_mem_free(msg_iov[1].iov_base);
|
||||
|
@ -845,6 +849,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
|
|||
|
||||
if (msg_tr_ptr->relay_start) {
|
||||
//Build Relay Reply only server do this
|
||||
int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
|
||||
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
ns_iovec_t data_vector[2];
|
||||
ns_msghdr_t msghdr;
|
||||
memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16);
|
||||
|
@ -872,6 +878,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
|
|||
retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0);
|
||||
|
||||
} else {
|
||||
int16_t tc = 0;
|
||||
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
|
||||
retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len);
|
||||
}
|
||||
if (retval != 0) {
|
||||
|
|
|
@ -165,6 +165,7 @@ SRCS += \
|
|||
source/Service_Libs/Trickle/trickle.c \
|
||||
source/Service_Libs/whiteboard/whiteboard.c \
|
||||
source/Service_Libs/pan_blacklist/pan_blacklist.c \
|
||||
source/Service_Libs/random_early_detection/random_early_detection.c \
|
||||
source/6LoWPAN/Thread/thread_management_if.c \
|
||||
source/6LoWPAN/Thread/thread_management_api.c \
|
||||
source/6LoWPAN/Thread/thread_commissioning_api.c \
|
||||
|
|
Loading…
Reference in New Issue