1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2017 Intel Corporation
5 #include <rte_malloc.h>
7 #include "ixgbe_ethdev.h"
9 static int ixgbe_tm_capabilities_get(struct rte_eth_dev
*dev
,
10 struct rte_tm_capabilities
*cap
,
11 struct rte_tm_error
*error
);
12 static int ixgbe_shaper_profile_add(struct rte_eth_dev
*dev
,
13 uint32_t shaper_profile_id
,
14 struct rte_tm_shaper_params
*profile
,
15 struct rte_tm_error
*error
);
16 static int ixgbe_shaper_profile_del(struct rte_eth_dev
*dev
,
17 uint32_t shaper_profile_id
,
18 struct rte_tm_error
*error
);
19 static int ixgbe_node_add(struct rte_eth_dev
*dev
, uint32_t node_id
,
20 uint32_t parent_node_id
, uint32_t priority
,
21 uint32_t weight
, uint32_t level_id
,
22 struct rte_tm_node_params
*params
,
23 struct rte_tm_error
*error
);
24 static int ixgbe_node_delete(struct rte_eth_dev
*dev
, uint32_t node_id
,
25 struct rte_tm_error
*error
);
26 static int ixgbe_node_type_get(struct rte_eth_dev
*dev
, uint32_t node_id
,
27 int *is_leaf
, struct rte_tm_error
*error
);
28 static int ixgbe_level_capabilities_get(struct rte_eth_dev
*dev
,
30 struct rte_tm_level_capabilities
*cap
,
31 struct rte_tm_error
*error
);
32 static int ixgbe_node_capabilities_get(struct rte_eth_dev
*dev
,
34 struct rte_tm_node_capabilities
*cap
,
35 struct rte_tm_error
*error
);
36 static int ixgbe_hierarchy_commit(struct rte_eth_dev
*dev
,
38 struct rte_tm_error
*error
);
40 const struct rte_tm_ops ixgbe_tm_ops
= {
41 .capabilities_get
= ixgbe_tm_capabilities_get
,
42 .shaper_profile_add
= ixgbe_shaper_profile_add
,
43 .shaper_profile_delete
= ixgbe_shaper_profile_del
,
44 .node_add
= ixgbe_node_add
,
45 .node_delete
= ixgbe_node_delete
,
46 .node_type_get
= ixgbe_node_type_get
,
47 .level_capabilities_get
= ixgbe_level_capabilities_get
,
48 .node_capabilities_get
= ixgbe_node_capabilities_get
,
49 .hierarchy_commit
= ixgbe_hierarchy_commit
,
53 ixgbe_tm_ops_get(struct rte_eth_dev
*dev __rte_unused
,
59 *(const void **)arg
= &ixgbe_tm_ops
;
65 ixgbe_tm_conf_init(struct rte_eth_dev
*dev
)
67 struct ixgbe_tm_conf
*tm_conf
=
68 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
70 /* initialize shaper profile list */
71 TAILQ_INIT(&tm_conf
->shaper_profile_list
);
73 /* initialize node configuration */
75 TAILQ_INIT(&tm_conf
->queue_list
);
76 TAILQ_INIT(&tm_conf
->tc_list
);
77 tm_conf
->nb_tc_node
= 0;
78 tm_conf
->nb_queue_node
= 0;
79 tm_conf
->committed
= false;
83 ixgbe_tm_conf_uninit(struct rte_eth_dev
*dev
)
85 struct ixgbe_tm_conf
*tm_conf
=
86 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
87 struct ixgbe_tm_shaper_profile
*shaper_profile
;
88 struct ixgbe_tm_node
*tm_node
;
90 /* clear node configuration */
91 while ((tm_node
= TAILQ_FIRST(&tm_conf
->queue_list
))) {
92 TAILQ_REMOVE(&tm_conf
->queue_list
, tm_node
, node
);
95 tm_conf
->nb_queue_node
= 0;
96 while ((tm_node
= TAILQ_FIRST(&tm_conf
->tc_list
))) {
97 TAILQ_REMOVE(&tm_conf
->tc_list
, tm_node
, node
);
100 tm_conf
->nb_tc_node
= 0;
102 rte_free(tm_conf
->root
);
103 tm_conf
->root
= NULL
;
106 /* Remove all shaper profiles */
107 while ((shaper_profile
=
108 TAILQ_FIRST(&tm_conf
->shaper_profile_list
))) {
109 TAILQ_REMOVE(&tm_conf
->shaper_profile_list
,
110 shaper_profile
, node
);
111 rte_free(shaper_profile
);
115 static inline uint8_t
116 ixgbe_tc_nb_get(struct rte_eth_dev
*dev
)
118 struct rte_eth_conf
*eth_conf
;
121 eth_conf
= &dev
->data
->dev_conf
;
122 if (eth_conf
->txmode
.mq_mode
== ETH_MQ_TX_DCB
) {
123 nb_tcs
= eth_conf
->tx_adv_conf
.dcb_tx_conf
.nb_tcs
;
124 } else if (eth_conf
->txmode
.mq_mode
== ETH_MQ_TX_VMDQ_DCB
) {
125 if (eth_conf
->tx_adv_conf
.vmdq_dcb_tx_conf
.nb_queue_pools
==
138 ixgbe_tm_capabilities_get(struct rte_eth_dev
*dev
,
139 struct rte_tm_capabilities
*cap
,
140 struct rte_tm_error
*error
)
142 struct ixgbe_hw
*hw
= IXGBE_DEV_PRIVATE_TO_HW(dev
->data
->dev_private
);
143 uint8_t tc_nb
= ixgbe_tc_nb_get(dev
);
148 if (tc_nb
> hw
->mac
.max_tx_queues
)
151 error
->type
= RTE_TM_ERROR_TYPE_NONE
;
153 /* set all the parameters to 0 first. */
154 memset(cap
, 0, sizeof(struct rte_tm_capabilities
));
157 * here is the max capability not the current configuration.
159 /* port + TCs + queues */
160 cap
->n_nodes_max
= 1 + IXGBE_DCB_MAX_TRAFFIC_CLASS
+
161 hw
->mac
.max_tx_queues
;
162 cap
->n_levels_max
= 3;
163 cap
->non_leaf_nodes_identical
= 1;
164 cap
->leaf_nodes_identical
= 1;
165 cap
->shaper_n_max
= cap
->n_nodes_max
;
166 cap
->shaper_private_n_max
= cap
->n_nodes_max
;
167 cap
->shaper_private_dual_rate_n_max
= 0;
168 cap
->shaper_private_rate_min
= 0;
169 /* 10Gbps -> 1.25GBps */
170 cap
->shaper_private_rate_max
= 1250000000ull;
171 cap
->shaper_shared_n_max
= 0;
172 cap
->shaper_shared_n_nodes_per_shaper_max
= 0;
173 cap
->shaper_shared_n_shapers_per_node_max
= 0;
174 cap
->shaper_shared_dual_rate_n_max
= 0;
175 cap
->shaper_shared_rate_min
= 0;
176 cap
->shaper_shared_rate_max
= 0;
177 cap
->sched_n_children_max
= hw
->mac
.max_tx_queues
;
179 * HW supports SP. But no plan to support it now.
180 * So, all the nodes should have the same priority.
182 cap
->sched_sp_n_priorities_max
= 1;
183 cap
->sched_wfq_n_children_per_group_max
= 0;
184 cap
->sched_wfq_n_groups_max
= 0;
186 * SW only supports fair round robin now.
187 * So, all the nodes should have the same weight.
189 cap
->sched_wfq_weight_max
= 1;
190 cap
->cman_head_drop_supported
= 0;
191 cap
->dynamic_update_mask
= 0;
192 cap
->shaper_pkt_length_adjust_min
= RTE_TM_ETH_FRAMING_OVERHEAD
;
193 cap
->shaper_pkt_length_adjust_max
= RTE_TM_ETH_FRAMING_OVERHEAD_FCS
;
194 cap
->cman_wred_context_n_max
= 0;
195 cap
->cman_wred_context_private_n_max
= 0;
196 cap
->cman_wred_context_shared_n_max
= 0;
197 cap
->cman_wred_context_shared_n_nodes_per_context_max
= 0;
198 cap
->cman_wred_context_shared_n_contexts_per_node_max
= 0;
204 static inline struct ixgbe_tm_shaper_profile
*
205 ixgbe_shaper_profile_search(struct rte_eth_dev
*dev
,
206 uint32_t shaper_profile_id
)
208 struct ixgbe_tm_conf
*tm_conf
=
209 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
210 struct ixgbe_shaper_profile_list
*shaper_profile_list
=
211 &tm_conf
->shaper_profile_list
;
212 struct ixgbe_tm_shaper_profile
*shaper_profile
;
214 TAILQ_FOREACH(shaper_profile
, shaper_profile_list
, node
) {
215 if (shaper_profile_id
== shaper_profile
->shaper_profile_id
)
216 return shaper_profile
;
223 ixgbe_shaper_profile_param_check(struct rte_tm_shaper_params
*profile
,
224 struct rte_tm_error
*error
)
226 /* min rate not supported */
227 if (profile
->committed
.rate
) {
228 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE
;
229 error
->message
= "committed rate not supported";
232 /* min bucket size not supported */
233 if (profile
->committed
.size
) {
234 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE
;
235 error
->message
= "committed bucket size not supported";
238 /* max bucket size not supported */
239 if (profile
->peak
.size
) {
240 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE
;
241 error
->message
= "peak bucket size not supported";
244 /* length adjustment not supported */
245 if (profile
->pkt_length_adjust
) {
246 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN
;
247 error
->message
= "packet length adjustment not supported";
255 ixgbe_shaper_profile_add(struct rte_eth_dev
*dev
,
256 uint32_t shaper_profile_id
,
257 struct rte_tm_shaper_params
*profile
,
258 struct rte_tm_error
*error
)
260 struct ixgbe_tm_conf
*tm_conf
=
261 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
262 struct ixgbe_tm_shaper_profile
*shaper_profile
;
265 if (!profile
|| !error
)
268 ret
= ixgbe_shaper_profile_param_check(profile
, error
);
272 shaper_profile
= ixgbe_shaper_profile_search(dev
, shaper_profile_id
);
274 if (shaper_profile
) {
275 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
;
276 error
->message
= "profile ID exist";
280 shaper_profile
= rte_zmalloc("ixgbe_tm_shaper_profile",
281 sizeof(struct ixgbe_tm_shaper_profile
),
285 shaper_profile
->shaper_profile_id
= shaper_profile_id
;
286 rte_memcpy(&shaper_profile
->profile
, profile
,
287 sizeof(struct rte_tm_shaper_params
));
288 TAILQ_INSERT_TAIL(&tm_conf
->shaper_profile_list
,
289 shaper_profile
, node
);
295 ixgbe_shaper_profile_del(struct rte_eth_dev
*dev
,
296 uint32_t shaper_profile_id
,
297 struct rte_tm_error
*error
)
299 struct ixgbe_tm_conf
*tm_conf
=
300 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
301 struct ixgbe_tm_shaper_profile
*shaper_profile
;
306 shaper_profile
= ixgbe_shaper_profile_search(dev
, shaper_profile_id
);
308 if (!shaper_profile
) {
309 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
;
310 error
->message
= "profile ID not exist";
314 /* don't delete a profile if it's used by one or several nodes */
315 if (shaper_profile
->reference_count
) {
316 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE
;
317 error
->message
= "profile in use";
321 TAILQ_REMOVE(&tm_conf
->shaper_profile_list
, shaper_profile
, node
);
322 rte_free(shaper_profile
);
327 static inline struct ixgbe_tm_node
*
328 ixgbe_tm_node_search(struct rte_eth_dev
*dev
, uint32_t node_id
,
329 enum ixgbe_tm_node_type
*node_type
)
331 struct ixgbe_tm_conf
*tm_conf
=
332 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
333 struct ixgbe_tm_node
*tm_node
;
335 if (tm_conf
->root
&& tm_conf
->root
->id
== node_id
) {
336 *node_type
= IXGBE_TM_NODE_TYPE_PORT
;
337 return tm_conf
->root
;
340 TAILQ_FOREACH(tm_node
, &tm_conf
->tc_list
, node
) {
341 if (tm_node
->id
== node_id
) {
342 *node_type
= IXGBE_TM_NODE_TYPE_TC
;
347 TAILQ_FOREACH(tm_node
, &tm_conf
->queue_list
, node
) {
348 if (tm_node
->id
== node_id
) {
349 *node_type
= IXGBE_TM_NODE_TYPE_QUEUE
;
358 ixgbe_queue_base_nb_get(struct rte_eth_dev
*dev
, uint16_t tc_node_no
,
359 uint16_t *base
, uint16_t *nb
)
361 uint8_t nb_tcs
= ixgbe_tc_nb_get(dev
);
362 struct rte_pci_device
*pci_dev
= RTE_ETH_DEV_TO_PCI(dev
);
363 uint16_t vf_num
= pci_dev
->max_vfs
;
372 if (vf_num
>= ETH_32_POOLS
) {
375 } else if (vf_num
>= ETH_16_POOLS
) {
385 *base
= vf_num
* nb_tcs
+ tc_node_no
;
389 if (nb_tcs
== ETH_8_TCS
) {
390 switch (tc_node_no
) {
427 switch (tc_node_no
) {
429 * If no VF and no DCB, only 64 queues can be used.
430 * This case also be covered by this "case 0".
456 ixgbe_node_param_check(struct rte_eth_dev
*dev
, uint32_t node_id
,
457 uint32_t priority
, uint32_t weight
,
458 struct rte_tm_node_params
*params
,
459 struct rte_tm_error
*error
)
461 if (node_id
== RTE_TM_NODE_ID_NULL
) {
462 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
463 error
->message
= "invalid node id";
468 error
->type
= RTE_TM_ERROR_TYPE_NODE_PRIORITY
;
469 error
->message
= "priority should be 0";
474 error
->type
= RTE_TM_ERROR_TYPE_NODE_WEIGHT
;
475 error
->message
= "weight must be 1";
479 /* not support shared shaper */
480 if (params
->shared_shaper_id
) {
481 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID
;
482 error
->message
= "shared shaper not supported";
485 if (params
->n_shared_shapers
) {
486 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS
;
487 error
->message
= "shared shaper not supported";
491 /* for non-leaf node */
492 if (node_id
>= dev
->data
->nb_tx_queues
) {
493 /* check the unsupported parameters */
494 if (params
->nonleaf
.wfq_weight_mode
) {
496 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE
;
497 error
->message
= "WFQ not supported";
500 if (params
->nonleaf
.n_sp_priorities
!= 1) {
502 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES
;
503 error
->message
= "SP priority not supported";
505 } else if (params
->nonleaf
.wfq_weight_mode
&&
506 !(*params
->nonleaf
.wfq_weight_mode
)) {
508 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE
;
509 error
->message
= "WFP should be byte mode";
517 /* check the unsupported parameters */
518 if (params
->leaf
.cman
) {
519 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN
;
520 error
->message
= "Congestion management not supported";
523 if (params
->leaf
.wred
.wred_profile_id
!=
524 RTE_TM_WRED_PROFILE_ID_NONE
) {
526 RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID
;
527 error
->message
= "WRED not supported";
530 if (params
->leaf
.wred
.shared_wred_context_id
) {
532 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID
;
533 error
->message
= "WRED not supported";
536 if (params
->leaf
.wred
.n_shared_wred_contexts
) {
538 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS
;
539 error
->message
= "WRED not supported";
547 * Now the TC and queue configuration is controlled by DCB.
548 * We need check if the node configuration follows the DCB configuration.
549 * In the future, we may use TM to cover DCB.
552 ixgbe_node_add(struct rte_eth_dev
*dev
, uint32_t node_id
,
553 uint32_t parent_node_id
, uint32_t priority
,
554 uint32_t weight
, uint32_t level_id
,
555 struct rte_tm_node_params
*params
,
556 struct rte_tm_error
*error
)
558 struct ixgbe_tm_conf
*tm_conf
=
559 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
560 enum ixgbe_tm_node_type node_type
= IXGBE_TM_NODE_TYPE_MAX
;
561 enum ixgbe_tm_node_type parent_node_type
= IXGBE_TM_NODE_TYPE_MAX
;
562 struct ixgbe_tm_shaper_profile
*shaper_profile
= NULL
;
563 struct ixgbe_tm_node
*tm_node
;
564 struct ixgbe_tm_node
*parent_node
;
570 if (!params
|| !error
)
573 /* if already committed */
574 if (tm_conf
->committed
) {
575 error
->type
= RTE_TM_ERROR_TYPE_UNSPECIFIED
;
576 error
->message
= "already committed";
580 ret
= ixgbe_node_param_check(dev
, node_id
, priority
, weight
,
585 /* check if the node ID is already used */
586 if (ixgbe_tm_node_search(dev
, node_id
, &node_type
)) {
587 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
588 error
->message
= "node id already used";
592 /* check the shaper profile id */
593 if (params
->shaper_profile_id
!= RTE_TM_SHAPER_PROFILE_ID_NONE
) {
594 shaper_profile
= ixgbe_shaper_profile_search(
595 dev
, params
->shaper_profile_id
);
596 if (!shaper_profile
) {
598 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID
;
599 error
->message
= "shaper profile not exist";
604 /* root node if not have a parent */
605 if (parent_node_id
== RTE_TM_NODE_ID_NULL
) {
607 if (level_id
!= RTE_TM_NODE_LEVEL_ID_ANY
&&
608 level_id
> IXGBE_TM_NODE_TYPE_PORT
) {
609 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARAMS
;
610 error
->message
= "Wrong level";
614 /* obviously no more than one root */
616 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID
;
617 error
->message
= "already have a root";
621 /* add the root node */
622 tm_node
= rte_zmalloc("ixgbe_tm_node",
623 sizeof(struct ixgbe_tm_node
),
627 tm_node
->id
= node_id
;
628 tm_node
->priority
= priority
;
629 tm_node
->weight
= weight
;
630 tm_node
->reference_count
= 0;
632 tm_node
->parent
= NULL
;
633 tm_node
->shaper_profile
= shaper_profile
;
634 rte_memcpy(&tm_node
->params
, params
,
635 sizeof(struct rte_tm_node_params
));
636 tm_conf
->root
= tm_node
;
638 /* increase the reference counter of the shaper profile */
640 shaper_profile
->reference_count
++;
645 /* TC or queue node */
646 /* check the parent node */
647 parent_node
= ixgbe_tm_node_search(dev
, parent_node_id
,
650 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID
;
651 error
->message
= "parent not exist";
654 if (parent_node_type
!= IXGBE_TM_NODE_TYPE_PORT
&&
655 parent_node_type
!= IXGBE_TM_NODE_TYPE_TC
) {
656 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID
;
657 error
->message
= "parent is not port or TC";
661 if (level_id
!= RTE_TM_NODE_LEVEL_ID_ANY
&&
662 level_id
!= parent_node_type
+ 1) {
663 error
->type
= RTE_TM_ERROR_TYPE_NODE_PARAMS
;
664 error
->message
= "Wrong level";
668 /* check the node number */
669 if (parent_node_type
== IXGBE_TM_NODE_TYPE_PORT
) {
670 /* check TC number */
671 nb_tcs
= ixgbe_tc_nb_get(dev
);
672 if (tm_conf
->nb_tc_node
>= nb_tcs
) {
673 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
674 error
->message
= "too many TCs";
678 /* check queue number */
679 if (tm_conf
->nb_queue_node
>= dev
->data
->nb_tx_queues
) {
680 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
681 error
->message
= "too many queues";
685 ixgbe_queue_base_nb_get(dev
, parent_node
->no
, &q_base
, &q_nb
);
686 if (parent_node
->reference_count
>= q_nb
) {
687 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
688 error
->message
= "too many queues than TC supported";
694 * For queue, the node id means queue id.
696 if (node_id
>= dev
->data
->nb_tx_queues
) {
697 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
698 error
->message
= "too large queue id";
703 /* add the TC or queue node */
704 tm_node
= rte_zmalloc("ixgbe_tm_node",
705 sizeof(struct ixgbe_tm_node
),
709 tm_node
->id
= node_id
;
710 tm_node
->priority
= priority
;
711 tm_node
->weight
= weight
;
712 tm_node
->reference_count
= 0;
713 tm_node
->parent
= parent_node
;
714 tm_node
->shaper_profile
= shaper_profile
;
715 rte_memcpy(&tm_node
->params
, params
,
716 sizeof(struct rte_tm_node_params
));
717 if (parent_node_type
== IXGBE_TM_NODE_TYPE_PORT
) {
718 tm_node
->no
= parent_node
->reference_count
;
719 TAILQ_INSERT_TAIL(&tm_conf
->tc_list
,
721 tm_conf
->nb_tc_node
++;
723 tm_node
->no
= q_base
+ parent_node
->reference_count
;
724 TAILQ_INSERT_TAIL(&tm_conf
->queue_list
,
726 tm_conf
->nb_queue_node
++;
728 tm_node
->parent
->reference_count
++;
730 /* increase the reference counter of the shaper profile */
732 shaper_profile
->reference_count
++;
738 ixgbe_node_delete(struct rte_eth_dev
*dev
, uint32_t node_id
,
739 struct rte_tm_error
*error
)
741 struct ixgbe_tm_conf
*tm_conf
=
742 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
743 enum ixgbe_tm_node_type node_type
= IXGBE_TM_NODE_TYPE_MAX
;
744 struct ixgbe_tm_node
*tm_node
;
749 /* if already committed */
750 if (tm_conf
->committed
) {
751 error
->type
= RTE_TM_ERROR_TYPE_UNSPECIFIED
;
752 error
->message
= "already committed";
756 if (node_id
== RTE_TM_NODE_ID_NULL
) {
757 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
758 error
->message
= "invalid node id";
762 /* check the if the node id exists */
763 tm_node
= ixgbe_tm_node_search(dev
, node_id
, &node_type
);
765 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
766 error
->message
= "no such node";
770 /* the node should have no child */
771 if (tm_node
->reference_count
) {
772 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
774 "cannot delete a node which has children";
779 if (node_type
== IXGBE_TM_NODE_TYPE_PORT
) {
780 if (tm_node
->shaper_profile
)
781 tm_node
->shaper_profile
->reference_count
--;
783 tm_conf
->root
= NULL
;
787 /* TC or queue node */
788 if (tm_node
->shaper_profile
)
789 tm_node
->shaper_profile
->reference_count
--;
790 tm_node
->parent
->reference_count
--;
791 if (node_type
== IXGBE_TM_NODE_TYPE_TC
) {
792 TAILQ_REMOVE(&tm_conf
->tc_list
, tm_node
, node
);
793 tm_conf
->nb_tc_node
--;
795 TAILQ_REMOVE(&tm_conf
->queue_list
, tm_node
, node
);
796 tm_conf
->nb_queue_node
--;
804 ixgbe_node_type_get(struct rte_eth_dev
*dev
, uint32_t node_id
,
805 int *is_leaf
, struct rte_tm_error
*error
)
807 enum ixgbe_tm_node_type node_type
= IXGBE_TM_NODE_TYPE_MAX
;
808 struct ixgbe_tm_node
*tm_node
;
810 if (!is_leaf
|| !error
)
813 if (node_id
== RTE_TM_NODE_ID_NULL
) {
814 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
815 error
->message
= "invalid node id";
819 /* check if the node id exists */
820 tm_node
= ixgbe_tm_node_search(dev
, node_id
, &node_type
);
822 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
823 error
->message
= "no such node";
827 if (node_type
== IXGBE_TM_NODE_TYPE_QUEUE
)
836 ixgbe_level_capabilities_get(struct rte_eth_dev
*dev
,
838 struct rte_tm_level_capabilities
*cap
,
839 struct rte_tm_error
*error
)
841 struct ixgbe_hw
*hw
= IXGBE_DEV_PRIVATE_TO_HW(dev
->data
->dev_private
);
846 if (level_id
>= IXGBE_TM_NODE_TYPE_MAX
) {
847 error
->type
= RTE_TM_ERROR_TYPE_LEVEL_ID
;
848 error
->message
= "too deep level";
853 if (level_id
== IXGBE_TM_NODE_TYPE_PORT
) {
854 cap
->n_nodes_max
= 1;
855 cap
->n_nodes_nonleaf_max
= 1;
856 cap
->n_nodes_leaf_max
= 0;
857 } else if (level_id
== IXGBE_TM_NODE_TYPE_TC
) {
859 cap
->n_nodes_max
= IXGBE_DCB_MAX_TRAFFIC_CLASS
;
860 cap
->n_nodes_nonleaf_max
= IXGBE_DCB_MAX_TRAFFIC_CLASS
;
861 cap
->n_nodes_leaf_max
= 0;
864 cap
->n_nodes_max
= hw
->mac
.max_tx_queues
;
865 cap
->n_nodes_nonleaf_max
= 0;
866 cap
->n_nodes_leaf_max
= hw
->mac
.max_tx_queues
;
869 cap
->non_leaf_nodes_identical
= true;
870 cap
->leaf_nodes_identical
= true;
872 if (level_id
!= IXGBE_TM_NODE_TYPE_QUEUE
) {
873 cap
->nonleaf
.shaper_private_supported
= true;
874 cap
->nonleaf
.shaper_private_dual_rate_supported
= false;
875 cap
->nonleaf
.shaper_private_rate_min
= 0;
876 /* 10Gbps -> 1.25GBps */
877 cap
->nonleaf
.shaper_private_rate_max
= 1250000000ull;
878 cap
->nonleaf
.shaper_shared_n_max
= 0;
879 if (level_id
== IXGBE_TM_NODE_TYPE_PORT
)
880 cap
->nonleaf
.sched_n_children_max
=
881 IXGBE_DCB_MAX_TRAFFIC_CLASS
;
883 cap
->nonleaf
.sched_n_children_max
=
884 hw
->mac
.max_tx_queues
;
885 cap
->nonleaf
.sched_sp_n_priorities_max
= 1;
886 cap
->nonleaf
.sched_wfq_n_children_per_group_max
= 0;
887 cap
->nonleaf
.sched_wfq_n_groups_max
= 0;
888 cap
->nonleaf
.sched_wfq_weight_max
= 1;
889 cap
->nonleaf
.stats_mask
= 0;
895 cap
->leaf
.shaper_private_supported
= true;
896 cap
->leaf
.shaper_private_dual_rate_supported
= false;
897 cap
->leaf
.shaper_private_rate_min
= 0;
898 /* 10Gbps -> 1.25GBps */
899 cap
->leaf
.shaper_private_rate_max
= 1250000000ull;
900 cap
->leaf
.shaper_shared_n_max
= 0;
901 cap
->leaf
.cman_head_drop_supported
= false;
902 cap
->leaf
.cman_wred_context_private_supported
= true;
903 cap
->leaf
.cman_wred_context_shared_n_max
= 0;
904 cap
->leaf
.stats_mask
= 0;
910 ixgbe_node_capabilities_get(struct rte_eth_dev
*dev
,
912 struct rte_tm_node_capabilities
*cap
,
913 struct rte_tm_error
*error
)
915 struct ixgbe_hw
*hw
= IXGBE_DEV_PRIVATE_TO_HW(dev
->data
->dev_private
);
916 enum ixgbe_tm_node_type node_type
= IXGBE_TM_NODE_TYPE_MAX
;
917 struct ixgbe_tm_node
*tm_node
;
922 if (node_id
== RTE_TM_NODE_ID_NULL
) {
923 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
924 error
->message
= "invalid node id";
928 /* check if the node id exists */
929 tm_node
= ixgbe_tm_node_search(dev
, node_id
, &node_type
);
931 error
->type
= RTE_TM_ERROR_TYPE_NODE_ID
;
932 error
->message
= "no such node";
936 cap
->shaper_private_supported
= true;
937 cap
->shaper_private_dual_rate_supported
= false;
938 cap
->shaper_private_rate_min
= 0;
939 /* 10Gbps -> 1.25GBps */
940 cap
->shaper_private_rate_max
= 1250000000ull;
941 cap
->shaper_shared_n_max
= 0;
943 if (node_type
== IXGBE_TM_NODE_TYPE_QUEUE
) {
944 cap
->leaf
.cman_head_drop_supported
= false;
945 cap
->leaf
.cman_wred_context_private_supported
= true;
946 cap
->leaf
.cman_wred_context_shared_n_max
= 0;
948 if (node_type
== IXGBE_TM_NODE_TYPE_PORT
)
949 cap
->nonleaf
.sched_n_children_max
=
950 IXGBE_DCB_MAX_TRAFFIC_CLASS
;
952 cap
->nonleaf
.sched_n_children_max
=
953 hw
->mac
.max_tx_queues
;
954 cap
->nonleaf
.sched_sp_n_priorities_max
= 1;
955 cap
->nonleaf
.sched_wfq_n_children_per_group_max
= 0;
956 cap
->nonleaf
.sched_wfq_n_groups_max
= 0;
957 cap
->nonleaf
.sched_wfq_weight_max
= 1;
966 ixgbe_hierarchy_commit(struct rte_eth_dev
*dev
,
968 struct rte_tm_error
*error
)
970 struct ixgbe_tm_conf
*tm_conf
=
971 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev
->data
->dev_private
);
972 struct ixgbe_tm_node
*tm_node
;
979 /* check the setting */
983 /* not support port max bandwidth yet */
984 if (tm_conf
->root
->shaper_profile
&&
985 tm_conf
->root
->shaper_profile
->profile
.peak
.rate
) {
986 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE
;
987 error
->message
= "no port max bandwidth";
991 /* HW not support TC max bandwidth */
992 TAILQ_FOREACH(tm_node
, &tm_conf
->tc_list
, node
) {
993 if (tm_node
->shaper_profile
&&
994 tm_node
->shaper_profile
->profile
.peak
.rate
) {
995 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE
;
996 error
->message
= "no TC max bandwidth";
1001 /* queue max bandwidth */
1002 TAILQ_FOREACH(tm_node
, &tm_conf
->queue_list
, node
) {
1003 if (tm_node
->shaper_profile
)
1004 bw
= tm_node
->shaper_profile
->profile
.peak
.rate
;
1008 /* interpret Bps to Mbps */
1009 bw
= bw
* 8 / 1000 / 1000;
1010 ret
= ixgbe_set_queue_rate_limit(dev
, tm_node
->no
, bw
);
1012 error
->type
= RTE_TM_ERROR_TYPE_SHAPER_PROFILE
;
1014 "failed to set queue max bandwidth";
1021 tm_conf
->committed
= true;
1025 /* clear all the traffic manager configuration */
1026 if (clear_on_fail
) {
1027 ixgbe_tm_conf_uninit(dev
);
1028 ixgbe_tm_conf_init(dev
);