Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 715ae9a693..3183d87e41

3183d87e41 Merge branch 'release_internal' into release_external
9e27a772f2 Disabled BR IID verify from DODAG ID
33ac7911cf Merge pull request #2548 from PelionIoT/sync_with_mbed_os
6f8b2829f4 compile out trace when not available
825373d3ef Add SPDX license identifier to Arm files
3ec3bc649d fixed warnings: static method defined but not used
ee34352ceb Check if RX channel needs to be updated when RX slot detected (#2540)
d59dc5d25e Fix doxygen 1.8.17 warnings (#2546)
1e0beb3e67 Update unit tests to support Ubuntu 2020_04 LTS (#2545)
b9b2ffd96b Fixed FHSS get retry period (#2543)
a0bf6aec91 Check if RX channel needs to be updated after broadcast received (#2539)
fde325eee2 Wi-SUN Neighbour ARO registration failure handling update:
1e1f9c66b0 RPL dio Handler update:
0421502e27 Asynch message advertiment enable added to DAO done when disabled.
0374f74013 Corrected memory leak on key storage allocation on low memory situation
23c2f7ed05 Disable ASYNCH messages at enter Local repair state.
c1df6b0d75 Added Poison_count check for First DIO time blocker.
944f934539 Added channel mask size to FHSS configuration (#2536)
20e79e05fc RPL Local repair disable clear advertised_dodag_membership_since_last_repair state
8a4638089a Fix doxygen comments (#2534)
fe06236e43 MAC ACK RX guarantee update
2388a80700 MAC layer send ack allways when it requirement's
29b387b697 RPL dao dynamic timeout
00bbd02f85 Don't allow TX slot length go below allowed minimum (#2528)
8333faa401 Out of memory improvement to remove packets from routing
0a12aebff9 Support channel plan IDs 1, 2 and 5 with NA and BZ bands (#2526)
ee4333da6f Wi-SUN Timing configuration is selected based on network size and data rate
a5b2a26eb2 WS: API to set PHY mode and Channel plan IDs as defined by FAN 1.1 (#2520)
b86a044911 Update nanostack v12.7.0 changelog (#2525)
35b95da122 Remove unnecessary files from release
0717432619 Merge remote-tracking branch 'origin/release_internal' into release_external
f68126b85a Adaptation layer MCPS confirmation handle update
e483a0748d Added OFDM configurations and FEC in RF config structure (#2513)
b88abfa1c2 BUG fix: Fixed broken Brodcast MAC overflow handling
9cad47826a Random early detection congestion API update
00aed73abc Modified the Wi-SUN stack Latency estimates a bit slower
6b83d821ea Remove periodic PAN version increase from Wi-SUN border router
ef670e21f3 Integrated ReD congestion packet drop to Wi-SUN bootstrap interface.
b956d9e983 Revert "Improved transmission in high traffic (#2511)" (#2512)
01749c2116 Improved transmission in high traffic (#2511)
3158e966e0 Adaption layer queue trace update
5a32f4a7bb Update changelog, random_early_detection_congestion_check nameupdate and minor comment fix.
b818f12c6d Extented network status for support dropped tx congestion packet.
11c0763f4d Added new service Random early detection
f2c358dc2b Optimized medium NWK MPL parameters to 40 second multicast interval (#2508)
c013bc7790 Added traces to EAPOL TX failure
c29ee94a20 Changed TLS return value to int32_t
501a2c8578 Added trace for mbed TLS errors
9d7cd22aa6 Updated change log
1290225b95 Corrected radius message memory allocation
7b1c59695b Removed trace print's
efb83934f6 Adaptation layer MCPS confirmation handle update
ac1025e7e9 Bug Fix: Accept only next possible BSI for detect BR reboot and drop unkown's.
58f0e56fe4 Updated change log
102e525b9a Nanostack now indicates connection down on RPL local repair start
395791d535 FHSS WS: Do not allow broadcast TX on unicast channel (#2501)
72f8ecb8d2 Updated changelog.md
237620827c Activated higher priority by traffic class CS6 for NS/NA and RPL, EAPOL/ DHCP Relay messages.
afbe9061b5 Adaptation layer update
13fb2bfdbb Update CHANGELOG.md
af81c48993 DIO init TX filter update
13a872c6b9 Fix typos in github template (#2498)
1af20e1aee Initial version of CHANGELOG (#2497)
d9874ede96 Feature update: Improved MAC TX queue purge
69264429f9 Wi-SUN Aro registration temporary address registation bug fix.
d3170ed50a Removed generic event and wrong trace info.
0db3486a7a Removed trace from place which is normal and not needed
a080f18d83 Added debug tarce for dropped unsecured and MPL packets.
51cd5646ed Wi-SUN NS probe update:
579f75684e Adaptation layer: Do not push CCA failed packet back to MAC (Wi-SUN) (#2487)

git-subtree-dir: connectivity/nanostack/sal-stack-nanostack
git-subtree-split: 3183d87e410d80b96042c143e586967dce2ff650
pull/14169/head
Arto Kinnunen 2021-01-19 11:53:20 +02:00
parent 48fcb2ba25
commit b0e699fe3e
76 changed files with 2065 additions and 532 deletions

568
Doxyfile

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -82,7 +82,7 @@ void tcp_test_drop_reset()
}
#endif
#ifdef FEA_TRACE_SUPPORT
#if defined(FEA_TRACE_SUPPORT) && MBED_CONF_MBED_TRACE_ENABLE && (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG)
static const char *trace_tcp_flags(uint16_t flags)
{
static char buf[9];
@ -1223,7 +1223,9 @@ buffer_t *tcp_up(buffer_t *buf)
seg_len++;
}
#if defined(FEA_TRACE_SUPPORT) && MBED_CONF_MBED_TRACE_ENABLE && (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG)
tr_debug("TCP_UP: dst_p=%d, src_p=%d, flags=%s", buf->dst_sa.port, buf->src_sa.port, trace_tcp_flags(flags));
#endif
/* clear flags that will be ignored */
flags &= ~(TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2019 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2019 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, 2019 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2016 by Andrey Butok. FNET Community.
*
***************************************************************************

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2016 by Andrey Butok. FNET Community.
*
***************************************************************************

View File

@ -1,5 +1,6 @@
/**************************************************************************
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
*

View File

@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2016 by Andrey Butok. FNET Community.
* Copyright 2008-2010 by Freescale Semiconductor, Inc.
* Copyright 2003 by Motorola SPS.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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