From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hemant Agrawal Subject: Re: [PATCH v4 2/2] ethdev: add traffic management API Date: Wed, 24 May 2017 16:58:17 +0530 Message-ID: <6d78246a-b633-e57c-0a6a-39a49e44f529@nxp.com> References: <1488589820-206947-2-git-send-email-cristian.dumitrescu@intel.com> <1495213972-109148-1-git-send-email-cristian.dumitrescu@intel.com> <1495213972-109148-3-git-send-email-cristian.dumitrescu@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 8bit Cc: , , , To: Cristian Dumitrescu , Return-path: Received: from NAM02-CY1-obe.outbound.protection.outlook.com (mail-cys01nam02on0066.outbound.protection.outlook.com [104.47.37.66]) by dpdk.org (Postfix) with ESMTP id 10D217CB9 for ; Wed, 24 May 2017 13:28:32 +0200 (CEST) In-Reply-To: <1495213972-109148-3-git-send-email-cristian.dumitrescu@intel.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" On 5/19/2017 10:42 PM, Cristian Dumitrescu wrote: > This patch introduces the generic ethdev API for the traffic manager > capability, which includes: hierarchical scheduling, traffic shaping, > congestion management, packet marking. > > Main features: > - Exposed as ethdev plugin capability (similar to rte_flow) > - Capability query API per port, per level and per node > - Scheduling algorithms: Strict Priority (SP), Weighed Fair Queuing (WFQ) > - Traffic shaping: single/dual rate, private (per node) and shared (by > multiple nodes) shapers > - Congestion management for hierarchy leaf nodes: algorithms of tail drop, > head drop, WRED; private (per node) and shared (by multiple nodes) WRED > contexts > - Packet marking: IEEE 802.1q (VLAN DEI), IETF RFC 3168 (IPv4/IPv6 ECN for > TCP and SCTP), IETF RFC 2597 (IPv4 / IPv6 DSCP) > > Signed-off-by: Cristian Dumitrescu > --- > Changes in v4: > - Implemented feedback from Hemant [6] > - Capability API: Reworked the port, level and node capability API > data structure to remove confusion due to "summary across all > nodes" approach, which made it unclear whether a particular > capability is supported by all nodes or by at least one node. > - Capability API: Added flags for "all nodes have identical > capability set" > - Suspended state: documented the required behavior in Doxygen > description > - Implemented feedback from Jerin [7] > - Node add: added level parameter (see new API function: > rte_tm_node_add_check_level()) > - RTE_TM_ETH_FRAMING_OVERHEAD, RTE_TM_ETH_FRAMING_OVERHEAD_FCS: > documented their usage in their Doxygen description > - Capability API: for each function, mention the related > capability field (Doxygen @see) > - stats_mask, capability_mask: document the enum flags used to > build each mask (Doxygen @see) > - Rename rte_tm_get_leaf_nodes() to > rte_tm_get_number_of_leaf_nodes() > - Doxygen: add @param[in, out] to the description of all API funcs > - Doxygen: fix hooks in doc/api/doxy-api-index.md > - Rename rte_tm_hierarchy_set() to rte_tm_hierarchy_commit(), improved > Doxygen description > - Node add, node delete: improved Doxygen description > - Fixed incorrect design assumption that packet-based weight mode for WFQ > is identical to WRR. As result, removed all references to WRR support. > Renamed the "scheduling mode" node parameters to "wfq_weight_mode". > > Changes in v3: > - Implemented feedback from Jerin [5] > - Changed naming convention: scheddev -> tm > - Improvements on the capability API: > - Specification of marking capabilities per color > - WFQ/WRR groups: sp_n_children_max -> > wfq_wrr_n_children_per_group_max, added wfq_wrr_n_groups_max, > improved description of both, improved description of > wfq_wrr_weight_max > - Dynamic updates: added KEEP_LEVEL and CHANGE_LEVEL for parent > update > - Enforced/documented restrictions for root node (node_add() and > update()) > - Enforced/documented shaper profile restrictions on PIR: PIR != 0, > PIR >= CIR > - Turned repetitive code in rte_tm.c into macro > - Removed dependency on rte_red.h file (added RED params to rte_tm.h) > - Color: removed "e_" from color names enum > - Fixed small Doxygen style issues > > Changes in v2: > - Implemented feedback from Hemant [4] > - Improvements on the capability API > - Added capability API for hierarchy level > - Merged stats capability into the capability API > - Added dynamic updates > - Added non-leaf/leaf union to the node capability structure > - Renamed sp_priority_min to sp_n_priorities_max, added > clarifications > - Fixed description for sp_n_children_max > - Clarified and enforced rule on node ID range for leaf and non-leaf nodes > - Added API functions to get node type (i.e. leaf/non-leaf): > get_leaf_nodes(), node_type_get() > - Added clarification for the root node: its creation, parent, role > - Macro NODE_ID_NULL as root node's parent > - Description of the node_add() and node_parent_update() API funcs > - Added clarification for the first time add vs. subsequent updates rule > - Cleaned up the description for the node_add() function > - Statistics API improvements > - Merged stats capability into the capability API > - Added API function node_stats_update() > - Added more stats per packet color > - Added more error types > - Fixed small Doxygen style issues > > Changes in v1 (since RFC [1]): > - Implemented as ethdev plugin (similar to rte_flow) as opposed to more > monolithic additions to ethdev itself > - Implemented feedback from Jerin [2] and Hemant [3]. Implemented all the > suggested items with only one exception, see the long list below, > hopefully nothing was forgotten. > - The item not done (hopefully for a good reason): driver-generated > object IDs. IMO the choice to have application-generated object IDs > adds marginal complexity to the driver (search ID function > required), but it provides huge simplification for the application. > The app does not need to worry about building & managing tree-like > structure for storing driver-generated object IDs, the app can use > its own convention for node IDs depending on the specific hierarchy > that it needs. Trivial example: identify all level-2 nodes with IDs > like 100, 200, 300, … and the level-3 nodes based on their level-2 > parents: 110, 120, 130, 140, …, 210, 220, 230, 240, …, 310, 320, > 330, … and level-4 nodes based on their level-3 parents: 111, 112, > 113, 114, …, 121, 122, 123, 124, …). Moreover, see the change log > for the other related simplification that was implemented: leaf > nodes now have predefined IDs that are the same with their Ethernet > TX queue ID ( therefore no translation is required for leaf nodes). > - Capability API. Done per port and per node as well. > - Dual rate shapers > - Added configuration of private shaper (per node) directly from the > shaper profile as part of node API (no shaper ID needed for private > shapers), while the shared shapers are configured outside of the node > API using shaper profile and communicated to the node using shared > shaper ID. So there is no configuration overhead for shared shapers if > the app does not use any of them. > - Leaf nodes now have predefined IDs that are the same with their Ethernet > TX queue ID (therefore no translation is required for leaf nodes). This > is also used to differentiate between a leaf node and a non-leaf node. > - Domain-specific errors to give a precise indication of the error cause > (same as done by rte_flow) > - Packet marking API > - Packet length optional adjustment for shapers, positive (e.g. for adding > Ethernet framing overhead of 20 bytes) or negative (e.g. for rate > limiting based on IP packet bytes) > > [1] RFC: http://dpdk.org/ml/archives/dev/2016-November/050956.html > [2] Jerin’s feedback on RFC: http://www.dpdk.org/ml/archives/dev/2017-January/054484.html > [3] Hemant’s feedback on RFC: http://www.dpdk.org/ml/archives/dev/2017-January/054866.html > [4] Hemant's feedback on v1: http://www.dpdk.org/ml/archives/dev/2017-February/058033.html > [5] Jerin's feedback on v1: http://www.dpdk.org/ml/archives/dev/2017-March/058895.html > [6] Hemant's feedback on v3: http://www.dpdk.org/ml/archives/dev/2017-March/062354.html > [7] Jerin's feedback on v3: http://www.dpdk.org/ml/archives/dev/2017-April/063429.html > > MAINTAINERS | 4 + > lib/librte_ether/Makefile | 5 +- > lib/librte_ether/rte_ether_version.map | 30 + > lib/librte_ether/rte_tm.c | 448 ++++++++ > lib/librte_ether/rte_tm.h | 1923 ++++++++++++++++++++++++++++++++ > lib/librte_ether/rte_tm_driver.h | 373 +++++++ > 6 files changed, 2782 insertions(+), 1 deletion(-) > create mode 100644 lib/librte_ether/rte_tm.c > create mode 100644 lib/librte_ether/rte_tm.h > create mode 100644 lib/librte_ether/rte_tm_driver.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index afb4cab..cdaf2ac 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -240,6 +240,10 @@ Flow API > M: Adrien Mazarguil > F: lib/librte_ether/rte_flow* > > +Traffic Management API > +M: Cristian Dumitrescu > +F: lib/librte_ether/rte_tm* > + > Crypto API > M: Declan Doherty > F: lib/librte_cryptodev/ > diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile > index 93fdde1..db692ae 100644 > --- a/lib/librte_ether/Makefile > +++ b/lib/librte_ether/Makefile > @@ -1,6 +1,6 @@ > # BSD LICENSE > # > -# Copyright(c) 2010-2016 Intel Corporation. All rights reserved. > +# Copyright(c) 2010-2017 Intel Corporation. All rights reserved. > # All rights reserved. > # > # Redistribution and use in source and binary forms, with or without > @@ -45,6 +45,7 @@ LIBABIVER := 6 > > SRCS-y += rte_ethdev.c > SRCS-y += rte_flow.c > +SRCS-y += rte_tm.c > > # > # Export include files > @@ -56,5 +57,7 @@ SYMLINK-y-include += rte_eth_ctrl.h > SYMLINK-y-include += rte_dev_info.h > SYMLINK-y-include += rte_flow.h > SYMLINK-y-include += rte_flow_driver.h > +SYMLINK-y-include += rte_tm.h > +SYMLINK-y-include += rte_tm_driver.h > > include $(RTE_SDK)/mk/rte.lib.mk > diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map > index ff056e8..7f39904 100644 > --- a/lib/librte_ether/rte_ether_version.map > +++ b/lib/librte_ether/rte_ether_version.map > @@ -161,4 +161,34 @@ DPDK_17.08 { > global: > > rte_eth_dev_tm_ops_get; > + rte_tm_get_leaf_nodes; > + rte_tm_node_type_get; > + rte_tm_capabilities_get; > + rte_tm_level_capabilities_get; > + rte_tm_node_capabilities_get; > + rte_tm_wred_profile_add; > + rte_tm_wred_profile_delete; > + rte_tm_shared_wred_context_add_update; > + rte_tm_shared_wred_context_delete; > + rte_tm_shaper_profile_add; > + rte_tm_shaper_profile_delete; > + rte_tm_shared_shaper_add_update; > + rte_tm_shared_shaper_delete; > + rte_tm_node_add; > + rte_tm_node_delete; > + rte_tm_node_suspend; > + rte_tm_node_resume; > + rte_tm_hierarchy_commit; > + rte_tm_node_parent_update; > + rte_tm_node_shaper_update; > + rte_tm_node_shared_shaper_update; > + rte_tm_node_stats_update; > + rte_tm_node_wfq_weight_mode_update; > + rte_tm_node_cman_update; > + rte_tm_node_wred_context_update; > + rte_tm_node_shared_wred_context_update; > + rte_tm_node_stats_read; > + rte_tm_mark_vlan_dei; > + rte_tm_mark_ip_ecn; > + rte_tm_mark_ip_dscp; > } DPDK_17.05 > diff --git a/lib/librte_ether/rte_tm.c b/lib/librte_ether/rte_tm.c > new file mode 100644 > index 0000000..2617a1a > --- /dev/null > +++ b/lib/librte_ether/rte_tm.c > @@ -0,0 +1,448 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2017 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include > + > +#include > +#include "rte_ethdev.h" > +#include "rte_tm_driver.h" > +#include "rte_tm.h" > + > +/* Get generic traffic manager operations structure from a port. */ > +const struct rte_tm_ops * > +rte_tm_ops_get(uint8_t port_id, struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + const struct rte_tm_ops *ops; > + > + if (!rte_eth_dev_is_valid_port(port_id)) { > + rte_tm_error_set(error, > + ENODEV, > + RTE_TM_ERROR_TYPE_UNSPECIFIED, > + NULL, > + rte_strerror(ENODEV)); > + return NULL; > + } > + > + if ((dev->dev_ops->tm_ops_get == NULL) || > + (dev->dev_ops->tm_ops_get(dev, &ops) != 0) || > + (ops == NULL)) { > + rte_tm_error_set(error, > + ENOSYS, > + RTE_TM_ERROR_TYPE_UNSPECIFIED, > + NULL, > + rte_strerror(ENOSYS)); > + return NULL; > + } > + > + return ops; > +} > + > +#define RTE_TM_FUNC(port_id, func) \ > +({ \ > + const struct rte_tm_ops *ops = \ > + rte_tm_ops_get(port_id, error); \ > + if (ops == NULL) \ > + return -rte_errno; \ > + \ > + if (ops->func == NULL) \ > + return -rte_tm_error_set(error, \ > + ENOSYS, \ > + RTE_TM_ERROR_TYPE_UNSPECIFIED, \ > + NULL, \ > + rte_strerror(ENOSYS)); \ > + \ > + ops->func; \ > +}) > + > +/* Get number of leaf nodes */ > +int > +rte_tm_get_number_of_leaf_nodes(uint8_t port_id, > + uint32_t *n_leaf_nodes, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + const struct rte_tm_ops *ops = > + rte_tm_ops_get(port_id, error); > + > + if (ops == NULL) > + return -rte_errno; > + > + if (n_leaf_nodes == NULL) { > + rte_tm_error_set(error, > + EINVAL, > + RTE_TM_ERROR_TYPE_UNSPECIFIED, > + NULL, > + rte_strerror(EINVAL)); > + return -rte_errno; > + } > + > + *n_leaf_nodes = dev->data->nb_tx_queues; > + return 0; > +} > + > +/* Check node type (leaf or non-leaf) */ > +int > +rte_tm_node_type_get(uint8_t port_id, > + uint32_t node_id, > + int *is_leaf, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_type_get)(dev, > + node_id, is_leaf, error); > +} > + > +/* Get node level */ > +int > +rte_tm_node_level_get(uint8_t port_id, > + uint32_t node_id, > + uint32_t *level_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_level_get)(dev, > + node_id, level_id, error); > +} > + > +/* Get capabilities */ > +int rte_tm_capabilities_get(uint8_t port_id, > + struct rte_tm_capabilities *cap, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, capabilities_get)(dev, > + cap, error); > +} > + > +/* Get level capabilities */ > +int rte_tm_level_capabilities_get(uint8_t port_id, > + uint32_t level_id, > + struct rte_tm_level_capabilities *cap, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, level_capabilities_get)(dev, > + level_id, cap, error); > +} > + > +/* Get node capabilities */ > +int rte_tm_node_capabilities_get(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_node_capabilities *cap, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_capabilities_get)(dev, > + node_id, cap, error); > +} > + > +/* Add WRED profile */ > +int rte_tm_wred_profile_add(uint8_t port_id, > + uint32_t wred_profile_id, > + struct rte_tm_wred_params *profile, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, wred_profile_add)(dev, > + wred_profile_id, profile, error); > +} > + > +/* Delete WRED profile */ > +int rte_tm_wred_profile_delete(uint8_t port_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, wred_profile_delete)(dev, > + wred_profile_id, error); > +} > + > +/* Add/update shared WRED context */ > +int rte_tm_shared_wred_context_add_update(uint8_t port_id, > + uint32_t shared_wred_context_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shared_wred_context_add_update)(dev, > + shared_wred_context_id, wred_profile_id, error); > +} > + > +/* Delete shared WRED context */ > +int rte_tm_shared_wred_context_delete(uint8_t port_id, > + uint32_t shared_wred_context_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shared_wred_context_delete)(dev, > + shared_wred_context_id, error); > +} > + > +/* Add shaper profile */ > +int rte_tm_shaper_profile_add(uint8_t port_id, > + uint32_t shaper_profile_id, > + struct rte_tm_shaper_params *profile, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shaper_profile_add)(dev, > + shaper_profile_id, profile, error); > +} > + > +/* Delete WRED profile */ > +int rte_tm_shaper_profile_delete(uint8_t port_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shaper_profile_delete)(dev, > + shaper_profile_id, error); > +} > + > +/* Add shared shaper */ > +int rte_tm_shared_shaper_add_update(uint8_t port_id, > + uint32_t shared_shaper_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shared_shaper_add_update)(dev, > + shared_shaper_id, shaper_profile_id, error); > +} > + > +/* Delete shared shaper */ > +int rte_tm_shared_shaper_delete(uint8_t port_id, > + uint32_t shared_shaper_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, shared_shaper_delete)(dev, > + shared_shaper_id, error); > +} > + > +/* Add node to port traffic manager hierarchy */ > +int rte_tm_node_add(uint8_t port_id, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_node_params *params, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_add)(dev, > + node_id, parent_node_id, priority, weight, params, error); > +} > + > +/* Delete node from traffic manager hierarchy */ > +int rte_tm_node_delete(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_delete)(dev, > + node_id, error); > +} > + > +/* Suspend node */ > +int rte_tm_node_suspend(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_suspend)(dev, > + node_id, error); > +} > + > +/* Resume node */ > +int rte_tm_node_resume(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_resume)(dev, > + node_id, error); > +} > + > +/* Commit the initial port traffic manager hierarchy */ > +int rte_tm_hierarchy_commit(uint8_t port_id, > + int clear_on_fail, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, hierarchy_commit)(dev, > + clear_on_fail, error); > +} > + > +/* Update node parent */ > +int rte_tm_node_parent_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_parent_update)(dev, > + node_id, parent_node_id, priority, weight, error); > +} > + > +/* Update node private shaper */ > +int rte_tm_node_shaper_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_shaper_update)(dev, > + node_id, shaper_profile_id, error); > +} > + > +/* Update node shared shapers */ > +int rte_tm_node_shared_shaper_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shared_shaper_id, > + int add, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_shared_shaper_update)(dev, > + node_id, shared_shaper_id, add, error); > +} > + > +/* Update node stats */ > +int rte_tm_node_stats_update(uint8_t port_id, > + uint32_t node_id, > + uint64_t stats_mask, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_stats_update)(dev, > + node_id, stats_mask, error); > +} > + > +/* Update WFQ weight mode */ > +int rte_tm_node_wfq_weight_mode_update(uint8_t port_id, > + uint32_t node_id, > + int *wfq_weight_mode, > + uint32_t n_sp_priorities, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_wfq_weight_mode_update)(dev, > + node_id, wfq_weight_mode, n_sp_priorities, error); > +} > + > +/* Update node congestion management mode */ > +int rte_tm_node_cman_update(uint8_t port_id, > + uint32_t node_id, > + enum rte_tm_cman_mode cman, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_cman_update)(dev, > + node_id, cman, error); > +} > + > +/* Update node private WRED context */ > +int rte_tm_node_wred_context_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_wred_context_update)(dev, > + node_id, wred_profile_id, error); > +} > + > +/* Update node shared WRED context */ > +int rte_tm_node_shared_wred_context_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shared_wred_context_id, > + int add, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_shared_wred_context_update)(dev, > + node_id, shared_wred_context_id, add, error); > +} > + > +/* Read and/or clear stats counters for specific node */ > +int rte_tm_node_stats_read(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_node_stats *stats, > + uint64_t *stats_mask, > + int clear, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, node_stats_read)(dev, > + node_id, stats, stats_mask, clear, error); > +} > + > +/* Packet marking - VLAN DEI */ > +int rte_tm_mark_vlan_dei(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, mark_vlan_dei)(dev, > + mark_green, mark_yellow, mark_red, error); > +} > + > +/* Packet marking - IPv4/IPv6 ECN */ > +int rte_tm_mark_ip_ecn(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, mark_ip_ecn)(dev, > + mark_green, mark_yellow, mark_red, error); > +} > + > +/* Packet marking - IPv4/IPv6 DSCP */ > +int rte_tm_mark_ip_dscp(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error) > +{ > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > + return RTE_TM_FUNC(port_id, mark_ip_dscp)(dev, > + mark_green, mark_yellow, mark_red, error); > +} > diff --git a/lib/librte_ether/rte_tm.h b/lib/librte_ether/rte_tm.h > new file mode 100644 > index 0000000..22167c2 > --- /dev/null > +++ b/lib/librte_ether/rte_tm.h > @@ -0,0 +1,1923 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2017 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef __INCLUDE_RTE_TM_H__ > +#define __INCLUDE_RTE_TM_H__ > + > +/** > + * @file > + * RTE Generic Traffic Manager API > + * > + * This interface provides the ability to configure the traffic manager in a > + * generic way. It includes features such as: hierarchical scheduling, > + * traffic shaping, congestion management, packet marking, etc. > + */ > + > +#include > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** > + * Ethernet framing overhead. > + * > + * Overhead fields per Ethernet frame: > + * 1. Preamble: 7 bytes; > + * 2. Start of Frame Delimiter (SFD): 1 byte; > + * 3. Inter-Frame Gap (IFG): 12 bytes. > + * > + * One of the typical values for the *pkt_length_adjust* field of the shaper > + * profile. > + * > + * @see struct rte_tm_shaper_params > + * > + */ > +#define RTE_TM_ETH_FRAMING_OVERHEAD 20 > + > +/** > + * Ethernet framing overhead including the Frame Check Sequence (FCS) field. > + * Useful when FCS is generated and added at the end of the Ethernet frame on > + * TX side without any SW intervention. > + * > + * One of the typical values for the pkt_length_adjust field of the shaper > + * profile. > + * > + * @see struct rte_tm_shaper_params > + */ > +#define RTE_TM_ETH_FRAMING_OVERHEAD_FCS 24 > + > +/**< Invalid WRED profile ID */ > +#define RTE_TM_WRED_PROFILE_ID_NONE UINT32_MAX > + > +/**< Invalid shaper profile ID */ > +#define RTE_TM_SHAPER_PROFILE_ID_NONE UINT32_MAX > + > +/**< Node ID for the parent of the root node */ > +#define RTE_TM_NODE_ID_NULL UINT32_MAX > + > +/** > + * Color > + */ > +enum rte_tm_color { > + RTE_TM_GREEN = 0, /**< Green */ > + RTE_TM_YELLOW, /**< Yellow */ > + RTE_TM_RED, /**< Red */ > + RTE_TM_COLORS /**< Number of colors */ > +}; > + > +/** > + * Node statistics counter type > + */ > +enum rte_tm_stats_type { > + /**< Number of packets scheduled from current node. */ > + RTE_TM_STATS_N_PKTS = 1 << 0, > + > + /**< Number of bytes scheduled from current node. */ > + RTE_TM_STATS_N_BYTES = 1 << 1, > + > + /**< Number of green packets dropped by current leaf node. */ > + RTE_TM_STATS_N_PKTS_GREEN_DROPPED = 1 << 2, > + > + /**< Number of yellow packets dropped by current leaf node. */ > + RTE_TM_STATS_N_PKTS_YELLOW_DROPPED = 1 << 3, > + > + /**< Number of red packets dropped by current leaf node. */ > + RTE_TM_STATS_N_PKTS_RED_DROPPED = 1 << 4, > + > + /**< Number of green bytes dropped by current leaf node. */ > + RTE_TM_STATS_N_BYTES_GREEN_DROPPED = 1 << 5, > + > + /**< Number of yellow bytes dropped by current leaf node. */ > + RTE_TM_STATS_N_BYTES_YELLOW_DROPPED = 1 << 6, > + > + /**< Number of red bytes dropped by current leaf node. */ > + RTE_TM_STATS_N_BYTES_RED_DROPPED = 1 << 7, > + > + /**< Number of packets currently waiting in the packet queue of current > + * leaf node. > + */ > + RTE_TM_STATS_N_PKTS_QUEUED = 1 << 8, > + > + /**< Number of bytes currently waiting in the packet queue of current > + * leaf node. > + */ > + RTE_TM_STATS_N_BYTES_QUEUED = 1 << 9, > +}; > + > +/** > + * Node statistics counters > + */ > +struct rte_tm_node_stats { > + /**< Number of packets scheduled from current node. */ > + uint64_t n_pkts; > + > + /**< Number of bytes scheduled from current node. */ > + uint64_t n_bytes; > + > + /**< Statistics counters for leaf nodes only. */ > + struct { > + /**< Number of packets dropped by current leaf node per each > + * color. > + */ > + uint64_t n_pkts_dropped[RTE_TM_COLORS]; > + > + /**< Number of bytes dropped by current leaf node per each > + * color. > + */ > + uint64_t n_bytes_dropped[RTE_TM_COLORS]; > + > + /**< Number of packets currently waiting in the packet queue of > + * current leaf node. > + */ > + uint64_t n_pkts_queued; > + > + /**< Number of bytes currently waiting in the packet queue of > + * current leaf node. > + */ > + uint64_t n_bytes_queued; > + } leaf; > +}; > + > +/** > + * Traffic manager dynamic updates > + */ > +enum rte_tm_dynamic_update_type { > + /**< Dynamic parent node update. The new parent node is located on same > + * hierarchy level as the former parent node. Consequently, the node > + * whose parent is changed preserves its hierarchy level. > + */ > + RTE_TM_UPDATE_NODE_PARENT_KEEP_LEVEL = 1 << 0, > + > + /**< Dynamic parent node update. The new parent node is located on > + * different hierarchy level than the former parent node. Consequently, > + * the node whose parent is changed also changes its hierarchy level. > + */ > + RTE_TM_UPDATE_NODE_PARENT_CHANGE_LEVEL = 1 << 1, > + > + /**< Dynamic node add/delete. */ > + RTE_TM_UPDATE_NODE_ADD_DELETE = 1 << 2, > + > + /**< Suspend/resume nodes. */ > + RTE_TM_UPDATE_NODE_SUSPEND_RESUME = 1 << 3, > + > + /**< Dynamic switch between byte-based and packet-based WFQ weights. */ > + RTE_TM_UPDATE_NODE_WFQ_WEIGHT_MODE = 1 << 4, > + > + /**< Dynamic update on number of SP priorities. */ > + RTE_TM_UPDATE_NODE_N_SP_PRIORITIES = 1 << 5, > + > + /**< Dynamic update of congestion management mode for leaf nodes. */ > + RTE_TM_UPDATE_NODE_CMAN = 1 << 6, > + > + /**< Dynamic update of the set of enabled stats counter types. */ > + RTE_TM_UPDATE_NODE_STATS = 1 << 7, > +}; > + > +/** > + * Traffic manager capabilities > + */ > +struct rte_tm_capabilities { > + /**< Maximum number of nodes. */ > + uint32_t n_nodes_max; > + > + /**< Maximum number of levels (i.e. number of nodes connecting the root > + * node with any leaf node, including the root and the leaf). > + */ > + uint32_t n_levels_max; > + > + /**< When non-zero, this flag indicates that all the non-leaf nodes > + * (with the exception of the root node) have identical capability set. > + */ > + int non_leaf_nodes_identical; > + > + /**< When non-zero, this flag indicates that all the leaf nodes have > + * identical capability set. > + */ > + int leaf_nodes_identical; > + > + /**< Maximum number of shapers, either private or shared. In case the > + * implementation does not share any resources between private and > + * shared shapers, it is typically equal to the sum of > + * *shaper_private_n_max* and *shaper_shared_n_max*. > + */ > + uint32_t shaper_n_max; > + > + /**< Maximum number of private shapers. Indicates the maximum number of > + * nodes that can concurrently have their private shaper enabled. > + */ > + uint32_t shaper_private_n_max; > + > + /**< Maximum number of private shapers that support dual rate shaping. > + * Indicates the maximum number of nodes that can concurrently have > + * their private shaper enabled with dual rate support. Only valid when > + * private shapers are supported. The value of zero indicates that dual > + * rate shaping is not available for private shapers. The maximum value > + * is *shaper_private_n_max*. > + */ > + int shaper_private_dual_rate_n_max; > + > + /**< Minimum committed/peak rate (bytes per second) for any private > + * shaper. Valid only when private shapers are supported. > + */ > + uint64_t shaper_private_rate_min; > + > + /**< Maximum committed/peak rate (bytes per second) for any private > + * shaper. Valid only when private shapers are supported. > + */ > + uint64_t shaper_private_rate_max; > + > + /**< Maximum number of shared shapers. The value of zero indicates that > + * shared shapers are not supported. > + */ > + uint32_t shaper_shared_n_max; > + > + /**< Maximum number of nodes that can share the same shared shaper. > + * Only valid when shared shapers are supported. > + */ > + uint32_t shaper_shared_n_nodes_per_shaper_max; > + > + /**< Maximum number of shared shapers a node can be part of. This > + * parameter indicates that there is at least one node that can be > + * configured with this many shared shapers, which might not be true for > + * all the nodes. Only valid when shared shapers are supported, in which > + * case it ranges from 1 to *shaper_shared_n_max*. > + */ > + uint32_t shaper_shared_n_shapers_per_node_max; > + > + /**< Maximum number of shared shapers that can be configured with dual > + * rate shaping. The value of zero indicates that dual rate shaping > + * support is not available for shared shapers. > + */ > + uint32_t shaper_shared_dual_rate_n_max; > + > + /**< Minimum committed/peak rate (bytes per second) for any shared > + * shaper. Only valid when shared shapers are supported. > + */ > + uint64_t shaper_shared_rate_min; > + > + /**< Maximum committed/peak rate (bytes per second) for any shared > + * shaper. Only valid when shared shapers are supported. > + */ > + uint64_t shaper_shared_rate_max; > + > + /**< Minimum value allowed for packet length adjustment for any private > + * or shared shaper. > + */ > + int shaper_pkt_length_adjust_min; > + > + /**< Maximum value allowed for packet length adjustment for any private > + * or shared shaper. > + */ > + int shaper_pkt_length_adjust_max; > + > + /**< Maximum number of children nodes. This parameter indicates that > + * there is at least one non-leaf node that can be configured with this > + * many children nodes, which might not be true for all the non-leaf > + * nodes. > + */ > + uint32_t sched_n_children_max; > + > + /**< Maximum number of supported priority levels. This parameter > + * indicates that there is at least one non-leaf node that can be > + * configured with this many priority levels for managing its children > + * nodes, which might not be true for all the non-leaf nodes. The value > + * of zero is invalid. The value of 1 indicates that only priority 0 is > + * supported, which essentially means that Strict Priority (SP) > + * algorithm is not supported. > + */ > + uint32_t sched_sp_n_priorities_max; > + > + /**< Maximum number of sibling nodes that can have the same priority at > + * any given time, i.e. maximum size of the WFQ sibling node group. This > + * parameter indicates there is at least one non-leaf node that meets > + * this condition, which might not be true for all the non-leaf nodes. > + * The value of zero is invalid. The value of 1 indicates that WFQ > + * algorithm is not supported. The maximum value is > + * *sched_n_children_max*. > + */ > + uint32_t sched_wfq_n_children_per_group_max; > + > + /**< Maximum number of priority levels that can have more than one child > + * node at any given time, i.e. maximum number of WFQ sibling node > + * groups that have two or more members. This parameter indicates there > + * is at least one non-leaf node that meets this condition, which might > + * not be true for all the non-leaf nodes. The value of zero states that > + * WFQ algorithm is not supported. The value of 1 indicates that > + * (*sched_sp_n_priorities_max* - 1) priority levels have at most one > + * child node, so there can be only one priority level with two or > + * more sibling nodes making up a WFQ group. The maximum value is: > + * min(floor(*sched_n_children_max* / 2), *sched_sp_n_priorities_max*). > + */ > + uint32_t sched_wfq_n_groups_max; > + > + /**< Maximum WFQ weight. The value of 1 indicates that all sibling nodes > + * with same priority have the same WFQ weight, so WFQ is reduced to FQ. > + */ > + uint32_t sched_wfq_weight_max; > + > + /**< Head drop algorithm support. When non-zero, this parameter > + * indicates that there is at least one leaf node that supports the head > + * drop algorithm, which might not be true for all the leaf nodes. > + */ > + int cman_head_drop_supported; > + > + /**< Maximum number of WRED contexts, either private or shared. In case > + * the implementation does not share any resources between private and > + * shared WRED contexts, it is typically equal to the sum of > + * *cman_wred_context_private_n_max* and > + * *cman_wred_context_shared_n_max*. > + */ > + uint32_t cman_wred_context_n_max; > + > + /**< Maximum number of private WRED contexts. Indicates the maximum > + * number of leaf nodes that can concurrently have their private WRED > + * context enabled. > + */ > + uint32_t cman_wred_context_private_n_max; > + > + /**< Maximum number of shared WRED contexts. The value of zero > + * indicates that shared WRED contexts are not supported. > + */ > + uint32_t cman_wred_context_shared_n_max; > + > + /**< Maximum number of leaf nodes that can share the same WRED context. > + * Only valid when shared WRED contexts are supported. > + */ > + uint32_t cman_wred_context_shared_n_nodes_per_context_max; > + > + /**< Maximum number of shared WRED contexts a leaf node can be part of. > + * This parameter indicates that there is at least one leaf node that > + * can be configured with this many shared WRED contexts, which might > + * not be true for all the leaf nodes. Only valid when shared WRED > + * contexts are supported, in which case it ranges from 1 to > + * *cman_wred_context_shared_n_max*. > + */ > + uint32_t cman_wred_context_shared_n_contexts_per_node_max; > + > + /**< Support for VLAN DEI packet marking (per color). */ > + int mark_vlan_dei_supported[RTE_TM_COLORS]; > + > + /**< Support for IPv4/IPv6 ECN marking of TCP packets (per color). */ > + int mark_ip_ecn_tcp_supported[RTE_TM_COLORS]; > + > + /**< Support for IPv4/IPv6 ECN marking of SCTP packets (per color). */ > + int mark_ip_ecn_sctp_supported[RTE_TM_COLORS]; > + > + /**< Support for IPv4/IPv6 DSCP packet marking (per color). */ > + int mark_ip_dscp_supported[RTE_TM_COLORS]; > + > + /**< Set of supported dynamic update operations. > + * @see enum rte_tm_dynamic_update_type > + */ > + uint64_t dynamic_update_mask; > + > + /**< Set of supported statistics counter types. > + * @see enum rte_tm_stats_type > + */ > + uint64_t stats_mask; > +}; > + > +/** > + * Traffic manager level capabilities > + */ > +struct rte_tm_level_capabilities { > + /**< Maximum number of nodes for the current hierarchy level. */ > + uint32_t n_nodes_max; > + > + /**< Maximum number of non-leaf nodes for the current hierarchy level. > + * The value of 0 indicates that current level only supports leaf > + * nodes. The maximum value is *n_nodes_max*. > + */ > + uint32_t n_nodes_nonleaf_max; > + > + /**< Maximum number of leaf nodes for the current hierarchy level. The > + * value of 0 indicates that current level only supports non-leaf > + * nodes. The maximum value is *n_nodes_max*. > + */ > + uint32_t n_nodes_leaf_max; > + > + /**< When non-zero, this flag indicates that all the non-leaf nodes on > + * this level have identical capability set. Valid only when > + * *n_nodes_nonleaf_max* is non-zero. > + */ > + int non_leaf_nodes_identical; > + > + /**< When non-zero, this flag indicates that all the leaf nodes on this > + * level have identical capability set. Valid only when > + * *n_nodes_leaf_max* is non-zero. > + */ > + int leaf_nodes_identical; > + > + union { > + /**< Items valid only for the non-leaf nodes on this level. */ > + struct { > + /**< Private shaper support. When non-zero, it indicates > + * there is at least one non-leaf node on this level > + * with private shaper support, which may not be the > + * case for all the non-leaf nodes on this level. > + */ > + int shaper_private_supported; > + > + /**< Dual rate support for private shaper. Valid only > + * when private shaper is supported for the non-leaf > + * nodes on the current level. When non-zero, it > + * indicates there is at least one non-leaf node on this > + * level with dual rate private shaper support, which > + * may not be the case for all the non-leaf nodes on > + * this level. > + */ > + int shaper_private_dual_rate_supported; > + > + /**< Minimum committed/peak rate (bytes per second) for > + * private shapers of the non-leaf nodes of this level. > + * Valid only when private shaper is supported on this > + * level. > + */ > + uint64_t shaper_private_rate_min; > + > + /**< Maximum committed/peak rate (bytes per second) for > + * private shapers of the non-leaf nodes on this level. > + * Valid only when private shaper is supported on this > + * level. > + */ > + uint64_t shaper_private_rate_max; > + > + /**< Maximum number of shared shapers that any non-leaf > + * node on this level can be part of. The value of zero > + * indicates that shared shapers are not supported by > + * the non-leaf nodes on this level. When non-zero, it > + * indicates there is at least one non-leaf node on this > + * level that meets this condition, which may not be the > + * case for all the non-leaf nodes on this level. > + */ > + uint32_t shaper_shared_n_max; > + > + /**< Maximum number of children nodes. This parameter > + * indicates that there is at least one non-leaf node on > + * this level that can be configured with this many > + * children nodes, which might not be true for all the > + * non-leaf nodes on this level. > + */ > + uint32_t sched_n_children_max; > + > + /**< Maximum number of supported priority levels. This > + * parameter indicates that there is at least one > + * non-leaf node on this level that can be configured > + * with this many priority levels for managing its > + * children nodes, which might not be true for all the > + * non-leaf nodes on this level. The value of zero is > + * invalid. The value of 1 indicates that only priority > + * 0 is supported, which essentially means that Strict > + * Priority (SP) algorithm is not supported on this > + * level. > + */ > + uint32_t sched_sp_n_priorities_max; > + > + /**< Maximum number of sibling nodes that can have the > + * same priority at any given time, i.e. maximum size of > + * the WFQ sibling node group. This parameter indicates > + * there is at least one non-leaf node on this level > + * that meets this condition, which may not be true for > + * all the non-leaf nodes on this level. The value of > + * zero is invalid. The value of 1 indicates that WFQ > + * algorithm is not supported on this level. The maximum > + * value is *sched_n_children_max*. > + */ > + uint32_t sched_wfq_n_children_per_group_max; > + > + /**< Maximum number of priority levels that can have > + * more than one child node at any given time, i.e. > + * maximum number of WFQ sibling node groups that > + * have two or more members. This parameter indicates > + * there is at least one non-leaf node on this level > + * that meets this condition, which might not be true > + * for all the non-leaf nodes. The value of zero states > + * that WFQ algorithm is not supported on this level. > + * The value of 1 indicates that > + * (*sched_sp_n_priorities_max* - 1) priority levels on > + * this level have at most one child node, so there can > + * be only one priority level with two or more sibling > + * nodes making up a WFQ group on this level. The > + * maximum value is: > + * min(floor(*sched_n_children_max* / 2), > + * *sched_sp_n_priorities_max*). > + */ > + uint32_t sched_wfq_n_groups_max; > + > + /**< Maximum WFQ weight. The value of 1 indicates that > + * all sibling nodes on this level with same priority > + * have the same WFQ weight, so on this level WFQ is > + * reduced to FQ. > + */ > + uint32_t sched_wfq_weight_max; > + > + /**< Mask of statistics counter types supported by the > + * non-leaf nodes on this level. Every supported > + * statistics counter type is supported by at least one > + * non-leaf node on this level, which may not be true > + * for all the non-leaf nodes on this level. > + * @see enum rte_tm_stats_type > + */ > + uint64_t stats_mask; > + } nonleaf; > + > + /**< Items valid only for the leaf nodes on this level. */ > + struct { > + /**< Private shaper support. When non-zero, it indicates > + * there is at least one leaf node on this level with > + * private shaper support, which may not be the case for > + * all the leaf nodes on this level. > + */ > + int shaper_private_supported; > + > + /**< Dual rate support for private shaper. Valid only > + * when private shaper is supported for the leaf nodes > + * on this level. When non-zero, it indicates there is > + * at least one leaf node on this level with dual rate > + * private shaper support, which may not be the case for > + * all the leaf nodes on this level. > + */ > + int shaper_private_dual_rate_supported; > + > + /**< Minimum committed/peak rate (bytes per second) for > + * private shapers of the leaf nodes of this level. > + * Valid only when private shaper is supported for the > + * leaf nodes on this level. > + */ > + uint64_t shaper_private_rate_min; > + > + /**< Maximum committed/peak rate (bytes per second) for > + * private shapers of the leaf nodes on this level. > + * Valid only when private shaper is supported for the > + * leaf nodes on this level. > + */ > + uint64_t shaper_private_rate_max; > + > + /**< Maximum number of shared shapers that any leaf node > + * on this level can be part of. The value of zero > + * indicates that shared shapers are not supported by > + * the leaf nodes on this level. When non-zero, it > + * indicates there is at least one leaf node on this > + * level that meets this condition, which may not be the > + * case for all the leaf nodes on this level. > + */ > + uint32_t shaper_shared_n_max; > + > + /**< Head drop algorithm support. When non-zero, this > + * parameter indicates that there is at least one leaf > + * node on this level that supports the head drop > + * algorithm, which might not be true for all the leaf > + * nodes on this level. > + */ > + int cman_head_drop_supported; > + > + /**< Private WRED context support. When non-zero, it > + * indicates there is at least one node on this level > + * with private WRED context support, which may not be > + * true for all the leaf nodes on this level. */ > + int cman_wred_context_private_supported; > + > + /**< Maximum number of shared WRED contexts that any > + * leaf node on this level can be part of. The value of > + * zero indicates that shared WRED contexts are not > + * supported by the leaf nodes on this level. When > + * non-zero, it indicates there is at least one leaf > + * node on this level that meets this condition, which > + * may not be the case for all the leaf nodes on this > + * level. > + */ > + uint32_t cman_wred_context_shared_n_max; > + > + /**< Mask of statistics counter types supported by the > + * leaf nodes on this level. Every supported statistics > + * counter type is supported by at least one leaf node > + * on this level, which may not be true for all the leaf > + * nodes on this level. > + * @see enum rte_tm_stats_type > + */ > + uint64_t stats_mask; > + } leaf; > + }; > +}; > + > +/** > + * Traffic manager node capabilities > + */ > +struct rte_tm_node_capabilities { > + /**< Private shaper support for the current node. */ > + int shaper_private_supported; > + > + /**< Dual rate shaping support for private shaper of current node. > + * Valid only when private shaper is supported by the current node. > + */ > + int shaper_private_dual_rate_supported; > + > + /**< Minimum committed/peak rate (bytes per second) for private > + * shaper of current node. Valid only when private shaper is supported > + * by the current node. > + */ > + uint64_t shaper_private_rate_min; > + > + /**< Maximum committed/peak rate (bytes per second) for private > + * shaper of current node. Valid only when private shaper is supported > + * by the current node. > + */ > + uint64_t shaper_private_rate_max; > + > + /**< Maximum number of shared shapers the current node can be part of. > + * The value of zero indicates that shared shapers are not supported by > + * the current node. > + */ > + uint32_t shaper_shared_n_max; > + > + union { > + /**< Items valid only for non-leaf nodes. */ > + struct { > + /**< Maximum number of children nodes. */ > + uint32_t sched_n_children_max; > + > + /**< Maximum number of supported priority levels. The > + * value of zero is invalid. The value of 1 indicates > + * that only priority 0 is supported, which essentially > + * means that Strict Priority (SP) algorithm is not > + * supported. > + */ > + uint32_t sched_sp_n_priorities_max; > + > + /**< Maximum number of sibling nodes that can have the > + * same priority at any given time, i.e. maximum size > + * of the WFQ sibling node group. The value of zero > + * is invalid. The value of 1 indicates that WFQ > + * algorithm is not supported. The maximum value is > + * *sched_n_children_max*. > + */ > + uint32_t sched_wfq_n_children_per_group_max; > + > + /**< Maximum number of priority levels that can have > + * more than one child node at any given time, i.e. > + * maximum number of WFQ sibling node groups that have > + * two or more members. The value of zero states that > + * WFQ algorithm is not supported. The value of 1 > + * indicates that (*sched_sp_n_priorities_max* - 1) > + * priority levels have at most one child node, so there > + * can be only one priority level with two or more > + * sibling nodes making up a WFQ group. The maximum > + * value is: min(floor(*sched_n_children_max* / 2), > + * *sched_sp_n_priorities_max*). > + */ > + uint32_t sched_wfq_n_groups_max; > + > + /**< Maximum WFQ weight. The value of 1 indicates that > + * all sibling nodes with same priority have the same > + * WFQ weight, so WFQ is reduced to FQ. > + */ > + uint32_t sched_wfq_weight_max; > + } nonleaf; > + > + /**< Items valid only for leaf nodes. */ > + struct { > + /**< Head drop algorithm support for current node. */ > + int cman_head_drop_supported; > + > + /**< Private WRED context support for current node. */ > + int cman_wred_context_private_supported; > + > + /**< Maximum number of shared WRED contexts the current > + * node can be part of. The value of zero indicates that > + * shared WRED contexts are not supported by the current > + * node. > + */ > + uint32_t cman_wred_context_shared_n_max; > + } leaf; > + }; > + > + /**< Mask of statistics counter types supported by the current node. > + * @see enum rte_tm_stats_type > + */ > + uint64_t stats_mask; > +}; > + > +/** > + * Congestion management (CMAN) mode > + * > + * This is used for controlling the admission of packets into a packet queue or > + * group of packet queues on congestion. On request of writing a new packet > + * into the current queue while the queue is full, the *tail drop* algorithm > + * drops the new packet while leaving the queue unmodified, as opposed to *head > + * drop* algorithm, which drops the packet at the head of the queue (the oldest > + * packet waiting in the queue) and admits the new packet at the tail of the > + * queue. > + * > + * The *Random Early Detection (RED)* algorithm works by proactively dropping > + * more and more input packets as the queue occupancy builds up. When the queue > + * is full or almost full, RED effectively works as *tail drop*. The *Weighted > + * RED* algorithm uses a separate set of RED thresholds for each packet color. > + */ > +enum rte_tm_cman_mode { > + RTE_TM_CMAN_TAIL_DROP = 0, /**< Tail drop */ > + RTE_TM_CMAN_HEAD_DROP, /**< Head drop */ > + RTE_TM_CMAN_WRED, /**< Weighted Random Early Detection (WRED) */ > +}; > + > +/** > + * Random Early Detection (RED) profile > + */ > +struct rte_tm_red_params { > + /**< Minimum queue threshold */ > + uint16_t min_th; > + > + /**< Maximum queue threshold */ > + uint16_t max_th; > + > + /**< Inverse of packet marking probability maximum value (maxp), i.e. > + * maxp_inv = 1 / maxp > + */ > + uint16_t maxp_inv; > + > + /**< Negated log2 of queue weight (wq), i.e. wq = 1 / (2 ^ wq_log2) */ > + uint16_t wq_log2; > +}; > + > +/** > + * Weighted RED (WRED) profile > + * > + * Multiple WRED contexts can share the same WRED profile. Each leaf node with > + * WRED enabled as its congestion management mode has zero or one private WRED > + * context (only one leaf node using it) and/or zero, one or several shared > + * WRED contexts (multiple leaf nodes use the same WRED context). A private > + * WRED context is used to perform congestion management for a single leaf > + * node, while a shared WRED context is used to perform congestion management > + * for a group of leaf nodes. > + */ > +struct rte_tm_wred_params { > + /**< One set of RED parameters per packet color */ > + struct rte_tm_red_params red_params[RTE_TM_COLORS]; > +}; > + > +/** > + * Token bucket > + */ > +struct rte_tm_token_bucket { > + /**< Token bucket rate (bytes per second) */ > + uint64_t rate; > + > + /**< Token bucket size (bytes), a.k.a. max burst size */ > + uint64_t size; > +}; > + > +/** > + * Shaper (rate limiter) profile > + * > + * Multiple shaper instances can share the same shaper profile. Each node has > + * zero or one private shaper (only one node using it) and/or zero, one or > + * several shared shapers (multiple nodes use the same shaper instance). > + * A private shaper is used to perform traffic shaping for a single node, while > + * a shared shaper is used to perform traffic shaping for a group of nodes. > + * > + * Single rate shapers use a single token bucket. A single rate shaper can be > + * configured by setting the rate of the committed bucket to zero, which > + * effectively disables this bucket. The peak bucket is used to limit the rate > + * and the burst size for the current shaper. > + * > + * Dual rate shapers use both the committed and the peak token buckets. The > + * rate of the peak bucket has to be bigger than zero, as well as greater than > + * or equal to the rate of the committed bucket. > + */ > +struct rte_tm_shaper_params { > + /**< Committed token bucket */ > + struct rte_tm_token_bucket committed; > + > + /**< Peak token bucket */ > + struct rte_tm_token_bucket peak; > + > + /**< Signed value to be added to the length of each packet for the > + * purpose of shaping. Can be used to correct the packet length with > + * the framing overhead bytes that are also consumed on the wire (e.g. > + * RTE_TM_ETH_FRAMING_OVERHEAD_FCS). > + */ > + int32_t pkt_length_adjust; > +}; > + > +/** > + * Node parameters > + * > + * Each non-leaf node has multiple inputs (its children nodes) and single output > + * (which is input to its parent node). It arbitrates its inputs using Strict > + * Priority (SP) and Weighted Fair Queuing (WFQ) algorithms to schedule input > + * packets to its output while observing its shaping (rate limiting) > + * constraints. > + * > + * Algorithms such as Weighted Round Robin (WRR), Byte-level WRR, Deficit WRR > + * (DWRR), etc. are considered approximations of the WFQ ideal and are > + * assimilated to WFQ, although an associated implementation-dependent trade-off > + * on accuracy, performance and resource usage might exist. > + * > + * Children nodes with different priorities are scheduled using the SP algorithm > + * based on their priority, with zero (0) as the highest priority. Children with > + * the same priority are scheduled using the WFQ algorithm according to their > + * weights. The WFQ weight of a given child node is relative to the sum of the > + * weights of all its sibling nodes that have the same priority, with one (1) as > + * the lowest weight. For each SP priority, the WFQ weight mode can be set as > + * either byte-based or packet-based. > + * > + * Each leaf node sits on top of a TX queue of the current Ethernet port. Hence, > + * the leaf nodes are predefined, with their node IDs set to 0 .. (N-1), where N > + * is the number of TX queues configured for the current Ethernet port. The > + * non-leaf nodes have their IDs generated by the application. > + */ > +struct rte_tm_node_params { > + /**< Shaper profile for the private shaper. The absence of the private > + * shaper for the current node is indicated by setting this parameter > + * to RTE_TM_SHAPER_PROFILE_ID_NONE. > + */ > + uint32_t shaper_profile_id; > + > + /**< User allocated array of valid shared shaper IDs. */ > + uint32_t *shared_shaper_id; > + > + /**< Number of shared shaper IDs in the *shared_shaper_id* array. */ > + uint32_t n_shared_shapers; > + > + union { > + /**< Parameters only valid for non-leaf nodes. */ > + struct { > + /**< WFQ weight mode for each SP priority. When NULL, it > + * indicates that WFQ is to be used for all priorities. > + * When non-NULL, it points to a pre-allocated array of > + * *n_sp_priorities* values, with non-zero value for > + * byte-mode and zero for packet-mode. > + */ > + int *wfq_weight_mode; > + > + /**< Number of SP priorities. */ > + uint32_t n_sp_priorities; > + } nonleaf; > + > + /**< Parameters only valid for leaf nodes. */ > + struct { > + /**< Congestion management mode */ > + enum rte_tm_cman_mode cman; > + > + /**< WRED parameters (only valid when *cman* is set to > + * WRED). > + */ > + struct { > + /**< WRED profile for private WRED context. The > + * absence of a private WRED context for the > + * current leaf node is indicated by value > + * RTE_TM_WRED_PROFILE_ID_NONE. > + */ > + uint32_t wred_profile_id; > + > + /**< User allocated array of shared WRED context > + * IDs. When set to NULL, it indicates that the > + * current leaf node should not currently be > + * part of any shared WRED contexts. > + */ > + uint32_t *shared_wred_context_id; > + > + /**< Number of elements in the > + * *shared_wred_context_id* array. Only valid > + * when *shared_wred_context_id* is non-NULL, > + * in which case it should be non-zero. > + */ > + uint32_t n_shared_wred_contexts; > + } wred; > + } leaf; > + }; > + > + /**< Mask of statistics counter types to be enabled for this node. This > + * needs to be a subset of the statistics counter types available for > + * the current node. Any statistics counter type not included in this > + * set is to be disabled for the current node. > + * @see enum rte_tm_stats_type > + */ > + uint64_t stats_mask; > +}; > + > +/** > + * Verbose error types. > + * > + * Most of them provide the type of the object referenced by struct > + * rte_tm_error::cause. > + */ > +enum rte_tm_error_type { > + RTE_TM_ERROR_TYPE_NONE, /**< No error. */ > + RTE_TM_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */ > + RTE_TM_ERROR_TYPE_CAPABILITIES, > + RTE_TM_ERROR_TYPE_LEVEL_ID, > + RTE_TM_ERROR_TYPE_WRED_PROFILE, > + RTE_TM_ERROR_TYPE_WRED_PROFILE_GREEN, > + RTE_TM_ERROR_TYPE_WRED_PROFILE_YELLOW, > + RTE_TM_ERROR_TYPE_WRED_PROFILE_RED, > + RTE_TM_ERROR_TYPE_WRED_PROFILE_ID, > + RTE_TM_ERROR_TYPE_SHARED_WRED_CONTEXT_ID, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN, > + RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID, > + RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID, > + RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID, > + RTE_TM_ERROR_TYPE_NODE_PRIORITY, > + RTE_TM_ERROR_TYPE_NODE_WEIGHT, > + RTE_TM_ERROR_TYPE_NODE_PARAMS, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS, > + RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS, > + RTE_TM_ERROR_TYPE_NODE_ID, > +}; > + > +/** > + * Verbose error structure definition. > + * > + * This object is normally allocated by applications and set by PMDs, the > + * message points to a constant string which does not need to be freed by > + * the application, however its pointer can be considered valid only as long > + * as its associated DPDK port remains configured. Closing the underlying > + * device or unloading the PMD invalidates it. > + * > + * Both cause and message may be NULL regardless of the error type. > + */ > +struct rte_tm_error { > + enum rte_tm_error_type type; /**< Cause field and error type. */ > + const void *cause; /**< Object responsible for the error. */ > + const char *message; /**< Human-readable error message. */ > +}; > + > +/** > + * Traffic manager get number of leaf nodes > + * > + * Each leaf node sits on on top of a TX queue of the current Ethernet port. > + * Therefore, the set of leaf nodes is predefined, their number is always equal > + * to N (where N is the number of TX queues configured for the current port) > + * and their IDs are 0 .. (N-1). > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[out] n_leaf_nodes > + * Number of leaf nodes for the current port. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_get_number_of_leaf_nodes(uint8_t port_id, > + uint32_t *n_leaf_nodes, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node type (i.e. leaf or non-leaf) get > + * > + * The leaf nodes have predefined IDs in the range of 0 .. (N-1), where N is > + * the number of TX queues of the current Ethernet port. The non-leaf nodes > + * have their IDs generated by the application outside of the above range, > + * which is reserved for leaf nodes. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID value. Needs to be valid. > + * @param[out] is_leaf > + * Set to non-zero value when node is leaf and to zero otherwise (non-leaf). > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_type_get(uint8_t port_id, > + uint32_t node_id, > + int *is_leaf, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node level get > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID value. Needs to be valid. > + * @param[out] level_id > + * Node level ID. Needs to be non-NULL. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_level_get(uint8_t port_id, > + uint32_t node_id, > + uint32_t *level_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager capabilities get > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[out] cap > + * Traffic manager capabilities. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_capabilities_get(uint8_t port_id, > + struct rte_tm_capabilities *cap, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager level capabilities get > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] level_id > + * The hierarchy level identifier. The value of 0 identifies the level of the > + * root node. > + * @param[out] cap > + * Traffic manager level capabilities. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_level_capabilities_get(uint8_t port_id, > + uint32_t level_id, > + struct rte_tm_level_capabilities *cap, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node capabilities get > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[out] cap > + * Traffic manager node capabilities. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_capabilities_get(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_node_capabilities *cap, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager WRED profile add > + * > + * Create a new WRED profile with ID set to *wred_profile_id*. The new profile > + * is used to create one or several WRED contexts. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] wred_profile_id > + * WRED profile ID for the new profile. Needs to be unused. > + * @param[in] profile > + * WRED profile parameters. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_wred_profile_add(uint8_t port_id, > + uint32_t wred_profile_id, > + struct rte_tm_wred_params *profile, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager WRED profile delete > + * > + * Delete an existing WRED profile. This operation fails when there is > + * currently at least one user (i.e. WRED context) of this WRED profile. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] wred_profile_id > + * WRED profile ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_wred_profile_delete(uint8_t port_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shared WRED context add or update > + * > + * When *shared_wred_context_id* is invalid, a new WRED context with this ID is > + * created by using the WRED profile identified by *wred_profile_id*. > + * > + * When *shared_wred_context_id* is valid, this WRED context is no longer using > + * the profile previously assigned to it and is updated to use the profile > + * identified by *wred_profile_id*. > + * > + * A valid shared WRED context can be assigned to several hierarchy leaf nodes > + * configured to use WRED as the congestion management mode. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shared_wred_context_id > + * Shared WRED context ID > + * @param[in] wred_profile_id > + * WRED profile ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shared_wred_context_add_update(uint8_t port_id, > + uint32_t shared_wred_context_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shared WRED context delete > + * > + * Delete an existing shared WRED context. This operation fails when there is > + * currently at least one user (i.e. hierarchy leaf node) of this shared WRED > + * context. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shared_wred_context_id > + * Shared WRED context ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shared_wred_context_delete(uint8_t port_id, > + uint32_t shared_wred_context_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shaper profile add > + * > + * Create a new shaper profile with ID set to *shaper_profile_id*. The new > + * shaper profile is used to create one or several shapers. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shaper_profile_id > + * Shaper profile ID for the new profile. Needs to be unused. > + * @param[in] profile > + * Shaper profile parameters. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shaper_profile_add(uint8_t port_id, > + uint32_t shaper_profile_id, > + struct rte_tm_shaper_params *profile, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shaper profile delete > + * > + * Delete an existing shaper profile. This operation fails when there is > + * currently at least one user (i.e. shaper) of this shaper profile. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shaper_profile_id > + * Shaper profile ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shaper_profile_delete(uint8_t port_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shared shaper add or update > + * > + * When *shared_shaper_id* is not a valid shared shaper ID, a new shared shaper > + * with this ID is created using the shaper profile identified by > + * *shaper_profile_id*. > + * > + * When *shared_shaper_id* is a valid shared shaper ID, this shared shaper is > + * no longer using the shaper profile previously assigned to it and is updated > + * to use the shaper profile identified by *shaper_profile_id*. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shared_shaper_id > + * Shared shaper ID > + * @param[in] shaper_profile_id > + * Shaper profile ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shared_shaper_add_update(uint8_t port_id, > + uint32_t shared_shaper_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager shared shaper delete > + * > + * Delete an existing shared shaper. This operation fails when there is > + * currently at least one user (i.e. hierarchy node) of this shared shaper. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] shared_shaper_id > + * Shared shaper ID. Needs to be the valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_shared_shaper_delete(uint8_t port_id, > + uint32_t shared_shaper_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node add > + * > + * Create new node and connect it as child of an existing node. The new node is > + * further identified by *node_id*, which needs to be unused by any of the > + * existing nodes. The parent node is identified by *parent_node_id*, which > + * needs to be the valid ID of an existing non-leaf node. The parent node is > + * going to use the provided SP *priority* and WFQ *weight* to schedule its new > + * child node. > + * > + * This function has to be called for both leaf and non-leaf nodes. In the case > + * of leaf nodes (i.e. *node_id* is within the range of 0 .. (N-1), with N as > + * the number of configured TX queues of the current port), the leaf node is > + * configured rather than created (as the set of leaf nodes is predefined) and > + * it is also connected as child of an existing node. > + * > + * The first node that is added becomes the root node and all the nodes that > + * are subsequently added have to be added as descendants of the root node. The > + * parent of the root node has to be specified as RTE_TM_NODE_ID_NULL and there > + * can only be one node with this parent ID (i.e. the root node). Further > + * restrictions for root node: needs to be non-leaf, its private shaper profile > + * needs to be valid and single rate, cannot use any shared shapers. > + * > + * When called before rte_tm_hierarchy_commit() invocation, this function is > + * typically used to define the initial start-up hierarchy for the port. > + * Provided that dynamic hierarchy updates are supported by the current port (as > + * advertised in the port capability set), this function can be also called > + * after the rte_tm_hierarchy_commit() invocation. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be unused by any of the existing nodes. > + * @param[in] parent_node_id > + * Parent node ID. Needs to be the valid. > + * @param[in] priority > + * Node priority. The highest node priority is zero. Used by the SP algorithm > + * running on the parent of the current node for scheduling this child node. > + * @param[in] weight > + * Node weight. The node weight is relative to the weight sum of all siblings > + * that have the same priority. The lowest weight is one. Used by the WFQ > + * algorithm running on the parent of the current node for scheduling this > + * child node. > + * @param[in] params > + * Node parameters. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see rte_tm_hierarchy_commit() > + * @see RTE_TM_UPDATE_NODE_ADD_DELETE > + */ > +int > +rte_tm_node_add(uint8_t port_id, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_node_params *params, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node add with node level check > + * > + * Simple rte_tm_node_add() wrapper that also checks the node level. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be unused by any of the existing nodes. > + * @param[in] parent_node_id > + * Parent node ID. Needs to be the valid. > + * @param[in] priority > + * Node priority. The highest node priority is zero. Used by the SP algorithm > + * running on the parent of the current node for scheduling this child node. > + * @param[in] weight > + * Node weight. The node weight is relative to the weight sum of all siblings > + * that have the same priority. The lowest weight is one. Used by the WFQ > + * algorithm running on the parent of the current node for scheduling this > + * child node. > + * @param[in] level_id > + * Level ID that should be met by this node. > + * @param[in] params > + * Node parameters. Needs to be pre-allocated and valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +static inline int > +rte_tm_node_add_check_level(uint8_t port_id, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + uint32_t level_id, > + struct rte_tm_node_params *params, > + struct rte_tm_error *error) > +{ > + uint32_t lid; > + int status; > + > + status = rte_tm_node_add(port_id, node_id, > + parent_node_id, priority, weight, params, error); > + if (status) > + return status; > + > + status = rte_tm_node_level_get(port_id, node_id, &lid, error); > + if (status) > + return status; > + > + if (lid != level_id){ > + if (error){ > + error->type = RTE_TM_ERROR_TYPE_LEVEL_ID; > + error->cause = NULL; > + error->message = rte_strerror(EINVAL); > + } > + rte_errno = EINVAL; > + return -EINVAL; > + } > + > + return 0; > +} > + > +/** > + * Traffic manager node delete > + * > + * Delete an existing node. This operation fails when this node currently has > + * at least one user (i.e. child node). > + * > + * When called before rte_tm_hierarchy_commit() invocation, this function is > + * typically used to define the initial start-up hierarchy for the port. > + * Provided that dynamic hierarchy updates are supported by the current port (as > + * advertised in the port capability set), this function can be also called > + * after the rte_tm_hierarchy_commit() invocation. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see RTE_TM_UPDATE_NODE_ADD_DELETE > + */ > +int > +rte_tm_node_delete(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node suspend > + * > + * Suspend an existing node. While the node is in suspended state, no packet is > + * scheduled from this node and its descendants. The node exits the suspended > + * state through the node resume operation. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see rte_tm_node_resume() > + * @see RTE_TM_UPDATE_NODE_SUSPEND_RESUME > + */ > +int > +rte_tm_node_suspend(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node resume > + * > + * Resume an existing node that is currently in suspended state. The node > + * entered the suspended state as result of a previous node suspend operation. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see rte_tm_node_suspend() > + * @see RTE_TM_UPDATE_NODE_SUSPEND_RESUME > + */ > +int > +rte_tm_node_resume(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager hierarchy commit > + * > + * This function is called during the port initialization phase (before the > + * Ethernet port is started) to freeze the start-up hierarchy. > + * > + * This function typically performs the following steps: > + * a) It validates the start-up hierarchy that was previously defined for the > + * current port through successive rte_tm_node_add() invocations; > + * b) Assuming successful validation, it performs all the necessary port > + * specific configuration operations to install the specified hierarchy on > + * the current port, with immediate effect once the port is started. > + * > + * This function fails when the currently configured hierarchy is not supported > + * by the Ethernet port, in which case the user can abort or try out another > + * hierarchy configuration (e.g. a hierarchy with less leaf nodes), which can be > + * build from scratch (when *clear_on_fail* is enabled) or by modifying the > + * existing hierarchy configuration (when *clear_on_fail* is disabled). > + * > + * Note that this function can still fail due to other causes (e.g. not enough > + * memory available in the system, etc), even though the specified hierarchy is > + * supported in principle by the current port. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] clear_on_fail > + * On function call failure, hierarchy is cleared when this parameter is > + * non-zero and preserved when this parameter is equal to zero. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see rte_tm_node_add() > + * @see rte_tm_node_delete() > + */ > +int > +rte_tm_hierarchy_commit(uint8_t port_id, > + int clear_on_fail, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node parent update > + * > + * Restriction for root node: its parent cannot be changed. > + * > + * This function can only be called after the rte_tm_hierarchy_commit() > + * invocation. Its success depends on the port support for this operation, as > + * advertised through the port capability set. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[in] parent_node_id > + * Node ID for the new parent. Needs to be valid. > + * @param[in] priority > + * Node priority. The highest node priority is zero. Used by the SP algorithm > + * running on the parent of the current node for scheduling this child node. > + * @param[in] weight > + * Node weight. The node weight is relative to the weight sum of all siblings > + * that have the same priority. The lowest weight is zero. Used by the WFQ > + * algorithm running on the parent of the current node for scheduling this > + * child node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see RTE_TM_UPDATE_NODE_PARENT_KEEP_LEVEL > + * @see RTE_TM_UPDATE_NODE_PARENT_CHANGE_LEVEL > + */ > +int > +rte_tm_node_parent_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node private shaper update > + * > + * Restriction for the root node: its private shaper profile needs to be valid > + * and single rate. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[in] shaper_profile_id > + * Shaper profile ID for the private shaper of the current node. Needs to be > + * either valid shaper profile ID or RTE_TM_SHAPER_PROFILE_ID_NONE, with > + * the latter disabling the private shaper of the current node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_shaper_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node shared shapers update > + * > + * Restriction for root node: cannot use any shared rate shapers. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[in] shared_shaper_id > + * Shared shaper ID. Needs to be valid. > + * @param[in] add > + * Set to non-zero value to add this shared shaper to current node or to zero > + * to delete this shared shaper from current node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_shared_shaper_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shared_shaper_id, > + int add, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node enabled statistics counters update > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[in] stats_mask > + * Mask of statistics counter types to be enabled for the current node. This > + * needs to be a subset of the statistics counter types available for the > + * current node. Any statistics counter type not included in this set is to > + * be disabled for the current node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see enum rte_tm_stats_type > + * @see RTE_TM_UPDATE_NODE_STATS > + */ > +int > +rte_tm_node_stats_update(uint8_t port_id, > + uint32_t node_id, > + uint64_t stats_mask, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node WFQ weight mode update > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid leaf node ID. > + * @param[in] wfq_weight_mode > + * WFQ weight mode for each SP priority. When NULL, it indicates that WFQ is > + * to be used for all priorities. When non-NULL, it points to a pre-allocated > + * array of *n_sp_priorities* values, with non-zero value for byte-mode and > + * zero for packet-mode. > + * @param[in] n_sp_priorities > + * Number of SP priorities. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see RTE_TM_UPDATE_NODE_WFQ_WEIGHT_MODE > + * @see RTE_TM_UPDATE_NODE_N_SP_PRIORITIES > + */ > +int > +rte_tm_node_wfq_weight_mode_update(uint8_t port_id, > + uint32_t node_id, > + int *wfq_weight_mode, > + uint32_t n_sp_priorities, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node congestion management mode update > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid leaf node ID. > + * @param[in] cman > + * Congestion management mode. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see RTE_TM_UPDATE_NODE_CMAN > + */ > +int > +rte_tm_node_cman_update(uint8_t port_id, > + uint32_t node_id, > + enum rte_tm_cman_mode cman, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node private WRED context update > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid leaf node ID. > + * @param[in] wred_profile_id > + * WRED profile ID for the private WRED context of the current node. Needs to > + * be either valid WRED profile ID or RTE_TM_WRED_PROFILE_ID_NONE, with the > + * latter disabling the private WRED context of the current node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_wred_context_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node shared WRED context update > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid leaf node ID. > + * @param[in] shared_wred_context_id > + * Shared WRED context ID. Needs to be valid. > + * @param[in] add > + * Set to non-zero value to add this shared WRED context to current node or > + * to zero to delete this shared WRED context from current node. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + */ > +int > +rte_tm_node_shared_wred_context_update(uint8_t port_id, > + uint32_t node_id, > + uint32_t shared_wred_context_id, > + int add, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager node statistics counters read > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] node_id > + * Node ID. Needs to be valid. > + * @param[out] stats > + * When non-NULL, it contains the current value for the statistics counters > + * enabled for the current node. > + * @param[out] stats_mask > + * When non-NULL, it contains the mask of statistics counter types that are > + * currently enabled for this node, indicating which of the counters > + * retrieved with the *stats* structure are valid. > + * @param[in] clear > + * When this parameter has a non-zero value, the statistics counters are > + * cleared (i.e. set to zero) immediately after they have been read, > + * otherwise the statistics counters are left untouched. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see enum rte_tm_stats_type > + */ > +int > +rte_tm_node_stats_read(uint8_t port_id, > + uint32_t node_id, > + struct rte_tm_node_stats *stats, > + uint64_t *stats_mask, > + int clear, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager packet marking - VLAN DEI (IEEE 802.1Q) > + * > + * IEEE 802.1p maps the traffic class to the VLAN Priority Code Point (PCP) > + * field (3 bits), while IEEE 802.1q maps the drop priority to the VLAN Drop > + * Eligible Indicator (DEI) field (1 bit), which was previously named Canonical > + * Format Indicator (CFI). > + * > + * All VLAN frames of a given color get their DEI bit set if marking is enabled > + * for this color; otherwise, their DEI bit is left as is (either set or not). > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] mark_green > + * Set to non-zero value to enable marking of green packets and to zero to > + * disable it. > + * @param[in] mark_yellow > + * Set to non-zero value to enable marking of yellow packets and to zero to > + * disable it. > + * @param[in] mark_red > + * Set to non-zero value to enable marking of red packets and to zero to > + * disable it. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see struct rte_tm_capabilities::mark_vlan_dei_supported > + */ > +int > +rte_tm_mark_vlan_dei(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager packet marking - IPv4 / IPv6 ECN (IETF RFC 3168) > + * > + * IETF RFCs 2474 and 3168 reorganize the IPv4 Type of Service (TOS) field > + * (8 bits) and the IPv6 Traffic Class (TC) field (8 bits) into Differentiated > + * Services Codepoint (DSCP) field (6 bits) and Explicit Congestion > + * Notification (ECN) field (2 bits). The DSCP field is typically used to > + * encode the traffic class and/or drop priority (RFC 2597), while the ECN > + * field is used by RFC 3168 to implement a congestion notification mechanism > + * to be leveraged by transport layer protocols such as TCP and SCTP that have > + * congestion control mechanisms. > + * > + * When congestion is experienced, as alternative to dropping the packet, > + * routers can change the ECN field of input packets from 2'b01 or 2'b10 > + * (values indicating that source endpoint is ECN-capable) to 2'b11 (meaning > + * that congestion is experienced). The destination endpoint can use the > + * ECN-Echo (ECE) TCP flag to relay the congestion indication back to the > + * source endpoint, which acknowledges it back to the destination endpoint with > + * the Congestion Window Reduced (CWR) TCP flag. > + * > + * All IPv4/IPv6 packets of a given color with ECN set to 2’b01 or 2’b10 > + * carrying TCP or SCTP have their ECN set to 2’b11 if the marking feature is > + * enabled for the current color, otherwise the ECN field is left as is. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] mark_green > + * Set to non-zero value to enable marking of green packets and to zero to > + * disable it. > + * @param[in] mark_yellow > + * Set to non-zero value to enable marking of yellow packets and to zero to > + * disable it. > + * @param[in] mark_red > + * Set to non-zero value to enable marking of red packets and to zero to > + * disable it. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see struct rte_tm_capabilities::mark_ip_ecn_tcp_supported > + * @see struct rte_tm_capabilities::mark_ip_ecn_sctp_supported > + */ > +int > +rte_tm_mark_ip_ecn(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > + > +/** > + * Traffic manager packet marking - IPv4 / IPv6 DSCP (IETF RFC 2597) > + * > + * IETF RFC 2597 maps the traffic class and the drop priority to the IPv4/IPv6 > + * Differentiated Services Codepoint (DSCP) field (6 bits). Here are the DSCP > + * values proposed by this RFC: > + * > + * Class 1 Class 2 Class 3 Class 4 > + * +----------+----------+----------+----------+ > + * Low Drop Prec | 001010 | 010010 | 011010 | 100010 | > + * Medium Drop Prec | 001100 | 010100 | 011100 | 100100 | > + * High Drop Prec | 001110 | 010110 | 011110 | 100110 | > + * +----------+----------+----------+----------+ > + * > + * There are 4 traffic classes (classes 1 .. 4) encoded by DSCP bits 1 and 2, > + * as well as 3 drop priorities (low/medium/high) encoded by DSCP bits 3 and 4. > + * > + * All IPv4/IPv6 packets have their color marked into DSCP bits 3 and 4 as > + * follows: green mapped to Low Drop Precedence (2’b01), yellow to Medium > + * (2’b10) and red to High (2’b11). Marking needs to be explicitly enabled > + * for each color; when not enabled for a given color, the DSCP field of all > + * packets with that color is left as is. > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[in] mark_green > + * Set to non-zero value to enable marking of green packets and to zero to > + * disable it. > + * @param[in] mark_yellow > + * Set to non-zero value to enable marking of yellow packets and to zero to > + * disable it. > + * @param[in] mark_red > + * Set to non-zero value to enable marking of red packets and to zero to > + * disable it. > + * @param[out] error > + * Error details. Filled in only on error, when not NULL. > + * @return > + * 0 on success, non-zero error code otherwise. > + * > + * @see struct rte_tm_capabilities::mark_ip_dscp_supported > + */ > +int > +rte_tm_mark_ip_dscp(uint8_t port_id, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* __INCLUDE_RTE_TM_H__ */ > diff --git a/lib/librte_ether/rte_tm_driver.h b/lib/librte_ether/rte_tm_driver.h > new file mode 100644 > index 0000000..c25f102 > --- /dev/null > +++ b/lib/librte_ether/rte_tm_driver.h > @@ -0,0 +1,373 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2017 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef __INCLUDE_RTE_TM_DRIVER_H__ > +#define __INCLUDE_RTE_TM_DRIVER_H__ > + > +/** > + * @file > + * RTE Generic Traffic Manager API (Driver Side) > + * > + * This file provides implementation helpers for internal use by PMDs, they > + * are not intended to be exposed to applications and are not subject to ABI > + * versioning. > + */ > + > +#include > + > +#include > +#include "rte_ethdev.h" > +#include "rte_tm.h" > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +typedef int (*rte_tm_node_type_get_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + int *is_leaf, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node type get */ > + > +typedef int (*rte_tm_node_level_get_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t *level_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node level get */ > + > +typedef int (*rte_tm_capabilities_get_t)(struct rte_eth_dev *dev, > + struct rte_tm_capabilities *cap, > + struct rte_tm_error *error); > +/**< @internal Traffic manager capabilities get */ > + > +typedef int (*rte_tm_level_capabilities_get_t)(struct rte_eth_dev *dev, > + uint32_t level_id, > + struct rte_tm_level_capabilities *cap, > + struct rte_tm_error *error); > +/**< @internal Traffic manager level capabilities get */ > + > +typedef int (*rte_tm_node_capabilities_get_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + struct rte_tm_node_capabilities *cap, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node capabilities get */ > + > +typedef int (*rte_tm_wred_profile_add_t)(struct rte_eth_dev *dev, > + uint32_t wred_profile_id, > + struct rte_tm_wred_params *profile, > + struct rte_tm_error *error); > +/**< @internal Traffic manager WRED profile add */ > + > +typedef int (*rte_tm_wred_profile_delete_t)(struct rte_eth_dev *dev, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager WRED profile delete */ > + > +typedef int (*rte_tm_shared_wred_context_add_update_t)( > + struct rte_eth_dev *dev, > + uint32_t shared_wred_context_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shared WRED context add */ > + > +typedef int (*rte_tm_shared_wred_context_delete_t)( > + struct rte_eth_dev *dev, > + uint32_t shared_wred_context_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shared WRED context delete */ > + > +typedef int (*rte_tm_shaper_profile_add_t)(struct rte_eth_dev *dev, > + uint32_t shaper_profile_id, > + struct rte_tm_shaper_params *profile, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shaper profile add */ > + > +typedef int (*rte_tm_shaper_profile_delete_t)(struct rte_eth_dev *dev, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shaper profile delete */ > + > +typedef int (*rte_tm_shared_shaper_add_update_t)(struct rte_eth_dev *dev, > + uint32_t shared_shaper_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shared shaper add/update */ > + > +typedef int (*rte_tm_shared_shaper_delete_t)(struct rte_eth_dev *dev, > + uint32_t shared_shaper_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager shared shaper delete */ > + > +typedef int (*rte_tm_node_add_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_node_params *params, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node add */ > + > +typedef int (*rte_tm_node_delete_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node delete */ > + > +typedef int (*rte_tm_node_suspend_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node suspend */ > + > +typedef int (*rte_tm_node_resume_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node resume */ > + > +typedef int (*rte_tm_hierarchy_commit_t)(struct rte_eth_dev *dev, > + int clear_on_fail, > + struct rte_tm_error *error); > +/**< @internal Traffic manager hierarchy commit */ > + > +typedef int (*rte_tm_node_parent_update_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t parent_node_id, > + uint32_t priority, > + uint32_t weight, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node parent update */ > + > +typedef int (*rte_tm_node_shaper_update_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t shaper_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node shaper update */ > + > +typedef int (*rte_tm_node_shared_shaper_update_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t shared_shaper_id, > + int32_t add, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node shaper update */ > + > +typedef int (*rte_tm_node_stats_update_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + uint64_t stats_mask, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node stats update */ > + > +typedef int (*rte_tm_node_wfq_weight_mode_update_t)( > + struct rte_eth_dev *dev, > + uint32_t node_id, > + int *wfq_weigth_mode, > + uint32_t n_sp_priorities, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node WFQ weight mode update */ > + > +typedef int (*rte_tm_node_cman_update_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + enum rte_tm_cman_mode cman, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node congestion management mode update */ > + > +typedef int (*rte_tm_node_wred_context_update_t)( > + struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t wred_profile_id, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node WRED context update */ > + > +typedef int (*rte_tm_node_shared_wred_context_update_t)( > + struct rte_eth_dev *dev, > + uint32_t node_id, > + uint32_t shared_wred_context_id, > + int add, > + struct rte_tm_error *error); > +/**< @internal Traffic manager node WRED context update */ > + > +typedef int (*rte_tm_node_stats_read_t)(struct rte_eth_dev *dev, > + uint32_t node_id, > + struct rte_tm_node_stats *stats, > + uint64_t *stats_mask, > + int clear, > + struct rte_tm_error *error); > +/**< @internal Traffic manager read stats counters for specific node */ > + > +typedef int (*rte_tm_mark_vlan_dei_t)(struct rte_eth_dev *dev, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > +/**< @internal Traffic manager packet marking - VLAN DEI */ > + > +typedef int (*rte_tm_mark_ip_ecn_t)(struct rte_eth_dev *dev, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > +/**< @internal Traffic manager packet marking - IPv4/IPv6 ECN */ > + > +typedef int (*rte_tm_mark_ip_dscp_t)(struct rte_eth_dev *dev, > + int mark_green, > + int mark_yellow, > + int mark_red, > + struct rte_tm_error *error); > +/**< @internal Traffic manager packet marking - IPv4/IPv6 DSCP */ > + > +struct rte_tm_ops { > + /** Traffic manager node type get */ > + rte_tm_node_type_get_t node_type_get; > + /** Traffic manager node level get */ > + rte_tm_node_level_get_t node_level_get; > + > + /** Traffic manager capabilities_get */ > + rte_tm_capabilities_get_t capabilities_get; > + /** Traffic manager level capabilities_get */ > + rte_tm_level_capabilities_get_t level_capabilities_get; > + /** Traffic manager node capabilities get */ > + rte_tm_node_capabilities_get_t node_capabilities_get; > + > + /** Traffic manager WRED profile add */ > + rte_tm_wred_profile_add_t wred_profile_add; > + /** Traffic manager WRED profile delete */ > + rte_tm_wred_profile_delete_t wred_profile_delete; > + /** Traffic manager shared WRED context add/update */ > + rte_tm_shared_wred_context_add_update_t > + shared_wred_context_add_update; > + /** Traffic manager shared WRED context delete */ > + rte_tm_shared_wred_context_delete_t > + shared_wred_context_delete; > + > + /** Traffic manager shaper profile add */ > + rte_tm_shaper_profile_add_t shaper_profile_add; > + /** Traffic manager shaper profile delete */ > + rte_tm_shaper_profile_delete_t shaper_profile_delete; > + /** Traffic manager shared shaper add/update */ > + rte_tm_shared_shaper_add_update_t shared_shaper_add_update; > + /** Traffic manager shared shaper delete */ > + rte_tm_shared_shaper_delete_t shared_shaper_delete; > + > + /** Traffic manager node add */ > + rte_tm_node_add_t node_add; > + /** Traffic manager node delete */ > + rte_tm_node_delete_t node_delete; > + /** Traffic manager node suspend */ > + rte_tm_node_suspend_t node_suspend; > + /** Traffic manager node resume */ > + rte_tm_node_resume_t node_resume; > + /** Traffic manager hierarchy commit */ > + rte_tm_hierarchy_commit_t hierarchy_commit; > + > + /** Traffic manager node parent update */ > + rte_tm_node_parent_update_t node_parent_update; > + /** Traffic manager node shaper update */ > + rte_tm_node_shaper_update_t node_shaper_update; > + /** Traffic manager node shared shaper update */ > + rte_tm_node_shared_shaper_update_t node_shared_shaper_update; > + /** Traffic manager node stats update */ > + rte_tm_node_stats_update_t node_stats_update; > + /** Traffic manager node WFQ weight mode update */ > + rte_tm_node_wfq_weight_mode_update_t node_wfq_weight_mode_update; > + /** Traffic manager node congestion management mode update */ > + rte_tm_node_cman_update_t node_cman_update; > + /** Traffic manager node WRED context update */ > + rte_tm_node_wred_context_update_t node_wred_context_update; > + /** Traffic manager node shared WRED context update */ > + rte_tm_node_shared_wred_context_update_t > + node_shared_wred_context_update; > + /** Traffic manager read statistics counters for current node */ > + rte_tm_node_stats_read_t node_stats_read; > + > + /** Traffic manager packet marking - VLAN DEI */ > + rte_tm_mark_vlan_dei_t mark_vlan_dei; > + /** Traffic manager packet marking - IPv4/IPv6 ECN */ > + rte_tm_mark_ip_ecn_t mark_ip_ecn; > + /** Traffic manager packet marking - IPv4/IPv6 DSCP */ > + rte_tm_mark_ip_dscp_t mark_ip_dscp; > +}; > + > +/** > + * Initialize generic error structure. > + * > + * This function also sets rte_errno to a given value. > + * > + * @param[out] error > + * Pointer to error structure (may be NULL). > + * @param[in] code > + * Related error code (rte_errno). > + * @param[in] type > + * Cause field and error type. > + * @param[in] cause > + * Object responsible for the error. > + * @param[in] message > + * Human-readable error message. > + * > + * @return > + * Error code. > + */ > +static inline int > +rte_tm_error_set(struct rte_tm_error *error, > + int code, > + enum rte_tm_error_type type, > + const void *cause, > + const char *message) > +{ > + if (error) { > + *error = (struct rte_tm_error){ > + .type = type, > + .cause = cause, > + .message = message, > + }; > + } > + rte_errno = code; > + return code; > +} > + > +/** > + * Get generic traffic manager operations structure from a port > + * > + * @param[in] port_id > + * The port identifier of the Ethernet device. > + * @param[out] error > + * Error details > + * > + * @return > + * The traffic manager operations structure associated with port_id on > + * success, NULL otherwise. > + */ > +const struct rte_tm_ops * > +rte_tm_ops_get(uint8_t port_id, struct rte_tm_error *error); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* __INCLUDE_RTE_TM_DRIVER_H__ */ > Acked-by: Hemant Agrawal