xref: /f-stack/dpdk/drivers/net/ixgbe/ixgbe_tm.c (revision 031be553)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <rte_malloc.h>
35 
36 #include "ixgbe_ethdev.h"
37 
38 static int ixgbe_tm_capabilities_get(struct rte_eth_dev *dev,
39 				     struct rte_tm_capabilities *cap,
40 				     struct rte_tm_error *error);
41 static int ixgbe_shaper_profile_add(struct rte_eth_dev *dev,
42 				    uint32_t shaper_profile_id,
43 				    struct rte_tm_shaper_params *profile,
44 				    struct rte_tm_error *error);
45 static int ixgbe_shaper_profile_del(struct rte_eth_dev *dev,
46 				    uint32_t shaper_profile_id,
47 				    struct rte_tm_error *error);
48 static int ixgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id,
49 			  uint32_t parent_node_id, uint32_t priority,
50 			  uint32_t weight, uint32_t level_id,
51 			  struct rte_tm_node_params *params,
52 			  struct rte_tm_error *error);
53 static int ixgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
54 			     struct rte_tm_error *error);
55 static int ixgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
56 			       int *is_leaf, struct rte_tm_error *error);
57 static int ixgbe_level_capabilities_get(struct rte_eth_dev *dev,
58 					uint32_t level_id,
59 					struct rte_tm_level_capabilities *cap,
60 					struct rte_tm_error *error);
61 static int ixgbe_node_capabilities_get(struct rte_eth_dev *dev,
62 				       uint32_t node_id,
63 				       struct rte_tm_node_capabilities *cap,
64 				       struct rte_tm_error *error);
65 static int ixgbe_hierarchy_commit(struct rte_eth_dev *dev,
66 				  int clear_on_fail,
67 				  struct rte_tm_error *error);
68 
69 const struct rte_tm_ops ixgbe_tm_ops = {
70 	.capabilities_get = ixgbe_tm_capabilities_get,
71 	.shaper_profile_add = ixgbe_shaper_profile_add,
72 	.shaper_profile_delete = ixgbe_shaper_profile_del,
73 	.node_add = ixgbe_node_add,
74 	.node_delete = ixgbe_node_delete,
75 	.node_type_get = ixgbe_node_type_get,
76 	.level_capabilities_get = ixgbe_level_capabilities_get,
77 	.node_capabilities_get = ixgbe_node_capabilities_get,
78 	.hierarchy_commit = ixgbe_hierarchy_commit,
79 };
80 
81 int
82 ixgbe_tm_ops_get(struct rte_eth_dev *dev __rte_unused,
83 		 void *arg)
84 {
85 	if (!arg)
86 		return -EINVAL;
87 
88 	*(const void **)arg = &ixgbe_tm_ops;
89 
90 	return 0;
91 }
92 
93 void
94 ixgbe_tm_conf_init(struct rte_eth_dev *dev)
95 {
96 	struct ixgbe_tm_conf *tm_conf =
97 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
98 
99 	/* initialize shaper profile list */
100 	TAILQ_INIT(&tm_conf->shaper_profile_list);
101 
102 	/* initialize node configuration */
103 	tm_conf->root = NULL;
104 	TAILQ_INIT(&tm_conf->queue_list);
105 	TAILQ_INIT(&tm_conf->tc_list);
106 	tm_conf->nb_tc_node = 0;
107 	tm_conf->nb_queue_node = 0;
108 	tm_conf->committed = false;
109 }
110 
111 void
112 ixgbe_tm_conf_uninit(struct rte_eth_dev *dev)
113 {
114 	struct ixgbe_tm_conf *tm_conf =
115 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
116 	struct ixgbe_tm_shaper_profile *shaper_profile;
117 	struct ixgbe_tm_node *tm_node;
118 
119 	/* clear node configuration */
120 	while ((tm_node = TAILQ_FIRST(&tm_conf->queue_list))) {
121 		TAILQ_REMOVE(&tm_conf->queue_list, tm_node, node);
122 		rte_free(tm_node);
123 	}
124 	tm_conf->nb_queue_node = 0;
125 	while ((tm_node = TAILQ_FIRST(&tm_conf->tc_list))) {
126 		TAILQ_REMOVE(&tm_conf->tc_list, tm_node, node);
127 		rte_free(tm_node);
128 	}
129 	tm_conf->nb_tc_node = 0;
130 	if (tm_conf->root) {
131 		rte_free(tm_conf->root);
132 		tm_conf->root = NULL;
133 	}
134 
135 	/* Remove all shaper profiles */
136 	while ((shaper_profile =
137 	       TAILQ_FIRST(&tm_conf->shaper_profile_list))) {
138 		TAILQ_REMOVE(&tm_conf->shaper_profile_list,
139 			     shaper_profile, node);
140 		rte_free(shaper_profile);
141 	}
142 }
143 
144 static inline uint8_t
145 ixgbe_tc_nb_get(struct rte_eth_dev *dev)
146 {
147 	struct rte_eth_conf *eth_conf;
148 	uint8_t nb_tcs = 0;
149 
150 	eth_conf = &dev->data->dev_conf;
151 	if (eth_conf->txmode.mq_mode == ETH_MQ_TX_DCB) {
152 		nb_tcs = eth_conf->tx_adv_conf.dcb_tx_conf.nb_tcs;
153 	} else if (eth_conf->txmode.mq_mode == ETH_MQ_TX_VMDQ_DCB) {
154 		if (eth_conf->tx_adv_conf.vmdq_dcb_tx_conf.nb_queue_pools ==
155 		    ETH_32_POOLS)
156 			nb_tcs = ETH_4_TCS;
157 		else
158 			nb_tcs = ETH_8_TCS;
159 	} else {
160 		nb_tcs = 1;
161 	}
162 
163 	return nb_tcs;
164 }
165 
166 static int
167 ixgbe_tm_capabilities_get(struct rte_eth_dev *dev,
168 			  struct rte_tm_capabilities *cap,
169 			  struct rte_tm_error *error)
170 {
171 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
172 	uint8_t tc_nb = ixgbe_tc_nb_get(dev);
173 
174 	if (!cap || !error)
175 		return -EINVAL;
176 
177 	if (tc_nb > hw->mac.max_tx_queues)
178 		return -EINVAL;
179 
180 	error->type = RTE_TM_ERROR_TYPE_NONE;
181 
182 	/* set all the parameters to 0 first. */
183 	memset(cap, 0, sizeof(struct rte_tm_capabilities));
184 
185 	/**
186 	 * here is the max capability not the current configuration.
187 	 */
188 	/* port + TCs + queues */
189 	cap->n_nodes_max = 1 + IXGBE_DCB_MAX_TRAFFIC_CLASS +
190 			   hw->mac.max_tx_queues;
191 	cap->n_levels_max = 3;
192 	cap->non_leaf_nodes_identical = 1;
193 	cap->leaf_nodes_identical = 1;
194 	cap->shaper_n_max = cap->n_nodes_max;
195 	cap->shaper_private_n_max = cap->n_nodes_max;
196 	cap->shaper_private_dual_rate_n_max = 0;
197 	cap->shaper_private_rate_min = 0;
198 	/* 10Gbps -> 1.25GBps */
199 	cap->shaper_private_rate_max = 1250000000ull;
200 	cap->shaper_shared_n_max = 0;
201 	cap->shaper_shared_n_nodes_per_shaper_max = 0;
202 	cap->shaper_shared_n_shapers_per_node_max = 0;
203 	cap->shaper_shared_dual_rate_n_max = 0;
204 	cap->shaper_shared_rate_min = 0;
205 	cap->shaper_shared_rate_max = 0;
206 	cap->sched_n_children_max = hw->mac.max_tx_queues;
207 	/**
208 	 * HW supports SP. But no plan to support it now.
209 	 * So, all the nodes should have the same priority.
210 	 */
211 	cap->sched_sp_n_priorities_max = 1;
212 	cap->sched_wfq_n_children_per_group_max = 0;
213 	cap->sched_wfq_n_groups_max = 0;
214 	/**
215 	 * SW only supports fair round robin now.
216 	 * So, all the nodes should have the same weight.
217 	 */
218 	cap->sched_wfq_weight_max = 1;
219 	cap->cman_head_drop_supported = 0;
220 	cap->dynamic_update_mask = 0;
221 	cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
222 	cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
223 	cap->cman_wred_context_n_max = 0;
224 	cap->cman_wred_context_private_n_max = 0;
225 	cap->cman_wred_context_shared_n_max = 0;
226 	cap->cman_wred_context_shared_n_nodes_per_context_max = 0;
227 	cap->cman_wred_context_shared_n_contexts_per_node_max = 0;
228 	cap->stats_mask = 0;
229 
230 	return 0;
231 }
232 
233 static inline struct ixgbe_tm_shaper_profile *
234 ixgbe_shaper_profile_search(struct rte_eth_dev *dev,
235 			    uint32_t shaper_profile_id)
236 {
237 	struct ixgbe_tm_conf *tm_conf =
238 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
239 	struct ixgbe_shaper_profile_list *shaper_profile_list =
240 		&tm_conf->shaper_profile_list;
241 	struct ixgbe_tm_shaper_profile *shaper_profile;
242 
243 	TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
244 		if (shaper_profile_id == shaper_profile->shaper_profile_id)
245 			return shaper_profile;
246 	}
247 
248 	return NULL;
249 }
250 
251 static int
252 ixgbe_shaper_profile_param_check(struct rte_tm_shaper_params *profile,
253 				 struct rte_tm_error *error)
254 {
255 	/* min rate not supported */
256 	if (profile->committed.rate) {
257 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
258 		error->message = "committed rate not supported";
259 		return -EINVAL;
260 	}
261 	/* min bucket size not supported */
262 	if (profile->committed.size) {
263 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
264 		error->message = "committed bucket size not supported";
265 		return -EINVAL;
266 	}
267 	/* max bucket size not supported */
268 	if (profile->peak.size) {
269 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
270 		error->message = "peak bucket size not supported";
271 		return -EINVAL;
272 	}
273 	/* length adjustment not supported */
274 	if (profile->pkt_length_adjust) {
275 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
276 		error->message = "packet length adjustment not supported";
277 		return -EINVAL;
278 	}
279 
280 	return 0;
281 }
282 
283 static int
284 ixgbe_shaper_profile_add(struct rte_eth_dev *dev,
285 			 uint32_t shaper_profile_id,
286 			 struct rte_tm_shaper_params *profile,
287 			 struct rte_tm_error *error)
288 {
289 	struct ixgbe_tm_conf *tm_conf =
290 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
291 	struct ixgbe_tm_shaper_profile *shaper_profile;
292 	int ret;
293 
294 	if (!profile || !error)
295 		return -EINVAL;
296 
297 	ret = ixgbe_shaper_profile_param_check(profile, error);
298 	if (ret)
299 		return ret;
300 
301 	shaper_profile = ixgbe_shaper_profile_search(dev, shaper_profile_id);
302 
303 	if (shaper_profile) {
304 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
305 		error->message = "profile ID exist";
306 		return -EINVAL;
307 	}
308 
309 	shaper_profile = rte_zmalloc("ixgbe_tm_shaper_profile",
310 				     sizeof(struct ixgbe_tm_shaper_profile),
311 				     0);
312 	if (!shaper_profile)
313 		return -ENOMEM;
314 	shaper_profile->shaper_profile_id = shaper_profile_id;
315 	rte_memcpy(&shaper_profile->profile, profile,
316 			 sizeof(struct rte_tm_shaper_params));
317 	TAILQ_INSERT_TAIL(&tm_conf->shaper_profile_list,
318 			  shaper_profile, node);
319 
320 	return 0;
321 }
322 
323 static int
324 ixgbe_shaper_profile_del(struct rte_eth_dev *dev,
325 			 uint32_t shaper_profile_id,
326 			 struct rte_tm_error *error)
327 {
328 	struct ixgbe_tm_conf *tm_conf =
329 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
330 	struct ixgbe_tm_shaper_profile *shaper_profile;
331 
332 	if (!error)
333 		return -EINVAL;
334 
335 	shaper_profile = ixgbe_shaper_profile_search(dev, shaper_profile_id);
336 
337 	if (!shaper_profile) {
338 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
339 		error->message = "profile ID not exist";
340 		return -EINVAL;
341 	}
342 
343 	/* don't delete a profile if it's used by one or several nodes */
344 	if (shaper_profile->reference_count) {
345 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
346 		error->message = "profile in use";
347 		return -EINVAL;
348 	}
349 
350 	TAILQ_REMOVE(&tm_conf->shaper_profile_list, shaper_profile, node);
351 	rte_free(shaper_profile);
352 
353 	return 0;
354 }
355 
356 static inline struct ixgbe_tm_node *
357 ixgbe_tm_node_search(struct rte_eth_dev *dev, uint32_t node_id,
358 		     enum ixgbe_tm_node_type *node_type)
359 {
360 	struct ixgbe_tm_conf *tm_conf =
361 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
362 	struct ixgbe_tm_node *tm_node;
363 
364 	if (tm_conf->root && tm_conf->root->id == node_id) {
365 		*node_type = IXGBE_TM_NODE_TYPE_PORT;
366 		return tm_conf->root;
367 	}
368 
369 	TAILQ_FOREACH(tm_node, &tm_conf->tc_list, node) {
370 		if (tm_node->id == node_id) {
371 			*node_type = IXGBE_TM_NODE_TYPE_TC;
372 			return tm_node;
373 		}
374 	}
375 
376 	TAILQ_FOREACH(tm_node, &tm_conf->queue_list, node) {
377 		if (tm_node->id == node_id) {
378 			*node_type = IXGBE_TM_NODE_TYPE_QUEUE;
379 			return tm_node;
380 		}
381 	}
382 
383 	return NULL;
384 }
385 
386 static void
387 ixgbe_queue_base_nb_get(struct rte_eth_dev *dev, uint16_t tc_node_no,
388 			uint16_t *base, uint16_t *nb)
389 {
390 	uint8_t nb_tcs = ixgbe_tc_nb_get(dev);
391 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
392 	uint16_t vf_num = pci_dev->max_vfs;
393 
394 	*base = 0;
395 	*nb = 0;
396 
397 	/* VT on */
398 	if (vf_num) {
399 		/* no DCB */
400 		if (nb_tcs == 1) {
401 			if (vf_num >= ETH_32_POOLS) {
402 				*nb = 2;
403 				*base = vf_num * 2;
404 			} else if (vf_num >= ETH_16_POOLS) {
405 				*nb = 4;
406 				*base = vf_num * 4;
407 			} else {
408 				*nb = 8;
409 				*base = vf_num * 8;
410 			}
411 		} else {
412 			/* DCB */
413 			*nb = 1;
414 			*base = vf_num * nb_tcs + tc_node_no;
415 		}
416 	} else {
417 		/* VT off */
418 		if (nb_tcs == ETH_8_TCS) {
419 			switch (tc_node_no) {
420 			case 0:
421 				*base = 0;
422 				*nb = 32;
423 				break;
424 			case 1:
425 				*base = 32;
426 				*nb = 32;
427 				break;
428 			case 2:
429 				*base = 64;
430 				*nb = 16;
431 				break;
432 			case 3:
433 				*base = 80;
434 				*nb = 16;
435 				break;
436 			case 4:
437 				*base = 96;
438 				*nb = 8;
439 				break;
440 			case 5:
441 				*base = 104;
442 				*nb = 8;
443 				break;
444 			case 6:
445 				*base = 112;
446 				*nb = 8;
447 				break;
448 			case 7:
449 				*base = 120;
450 				*nb = 8;
451 				break;
452 			default:
453 				return;
454 			}
455 		} else {
456 			switch (tc_node_no) {
457 			/**
458 			 * If no VF and no DCB, only 64 queues can be used.
459 			 * This case also be covered by this "case 0".
460 			 */
461 			case 0:
462 				*base = 0;
463 				*nb = 64;
464 				break;
465 			case 1:
466 				*base = 64;
467 				*nb = 32;
468 				break;
469 			case 2:
470 				*base = 96;
471 				*nb = 16;
472 				break;
473 			case 3:
474 				*base = 112;
475 				*nb = 16;
476 				break;
477 			default:
478 				return;
479 			}
480 		}
481 	}
482 }
483 
484 static int
485 ixgbe_node_param_check(struct rte_eth_dev *dev, uint32_t node_id,
486 		       uint32_t priority, uint32_t weight,
487 		       struct rte_tm_node_params *params,
488 		       struct rte_tm_error *error)
489 {
490 	if (node_id == RTE_TM_NODE_ID_NULL) {
491 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
492 		error->message = "invalid node id";
493 		return -EINVAL;
494 	}
495 
496 	if (priority) {
497 		error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
498 		error->message = "priority should be 0";
499 		return -EINVAL;
500 	}
501 
502 	if (weight != 1) {
503 		error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
504 		error->message = "weight must be 1";
505 		return -EINVAL;
506 	}
507 
508 	/* not support shared shaper */
509 	if (params->shared_shaper_id) {
510 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
511 		error->message = "shared shaper not supported";
512 		return -EINVAL;
513 	}
514 	if (params->n_shared_shapers) {
515 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
516 		error->message = "shared shaper not supported";
517 		return -EINVAL;
518 	}
519 
520 	/* for non-leaf node */
521 	if (node_id >= dev->data->nb_tx_queues) {
522 		/* check the unsupported parameters */
523 		if (params->nonleaf.wfq_weight_mode) {
524 			error->type =
525 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
526 			error->message = "WFQ not supported";
527 			return -EINVAL;
528 		}
529 		if (params->nonleaf.n_sp_priorities != 1) {
530 			error->type =
531 				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
532 			error->message = "SP priority not supported";
533 			return -EINVAL;
534 		} else if (params->nonleaf.wfq_weight_mode &&
535 			   !(*params->nonleaf.wfq_weight_mode)) {
536 			error->type =
537 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
538 			error->message = "WFP should be byte mode";
539 			return -EINVAL;
540 		}
541 
542 		return 0;
543 	}
544 
545 	/* for leaf node */
546 	/* check the unsupported parameters */
547 	if (params->leaf.cman) {
548 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
549 		error->message = "Congestion management not supported";
550 		return -EINVAL;
551 	}
552 	if (params->leaf.wred.wred_profile_id !=
553 	    RTE_TM_WRED_PROFILE_ID_NONE) {
554 		error->type =
555 			RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
556 		error->message = "WRED not supported";
557 		return -EINVAL;
558 	}
559 	if (params->leaf.wred.shared_wred_context_id) {
560 		error->type =
561 			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
562 		error->message = "WRED not supported";
563 		return -EINVAL;
564 	}
565 	if (params->leaf.wred.n_shared_wred_contexts) {
566 		error->type =
567 			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
568 		error->message = "WRED not supported";
569 		return -EINVAL;
570 	}
571 
572 	return 0;
573 }
574 
575 /**
576  * Now the TC and queue configuration is controlled by DCB.
577  * We need check if the node configuration follows the DCB configuration.
578  * In the future, we may use TM to cover DCB.
579  */
580 static int
581 ixgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id,
582 	       uint32_t parent_node_id, uint32_t priority,
583 	       uint32_t weight, uint32_t level_id,
584 	       struct rte_tm_node_params *params,
585 	       struct rte_tm_error *error)
586 {
587 	struct ixgbe_tm_conf *tm_conf =
588 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
589 	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
590 	enum ixgbe_tm_node_type parent_node_type = IXGBE_TM_NODE_TYPE_MAX;
591 	struct ixgbe_tm_shaper_profile *shaper_profile = NULL;
592 	struct ixgbe_tm_node *tm_node;
593 	struct ixgbe_tm_node *parent_node;
594 	uint8_t nb_tcs;
595 	uint16_t q_base = 0;
596 	uint16_t q_nb = 0;
597 	int ret;
598 
599 	if (!params || !error)
600 		return -EINVAL;
601 
602 	/* if already committed */
603 	if (tm_conf->committed) {
604 		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
605 		error->message = "already committed";
606 		return -EINVAL;
607 	}
608 
609 	ret = ixgbe_node_param_check(dev, node_id, priority, weight,
610 				     params, error);
611 	if (ret)
612 		return ret;
613 
614 	/* check if the node ID is already used */
615 	if (ixgbe_tm_node_search(dev, node_id, &node_type)) {
616 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
617 		error->message = "node id already used";
618 		return -EINVAL;
619 	}
620 
621 	/* check the shaper profile id */
622 	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
623 		shaper_profile = ixgbe_shaper_profile_search(
624 					dev, params->shaper_profile_id);
625 		if (!shaper_profile) {
626 			error->type =
627 				RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
628 			error->message = "shaper profile not exist";
629 			return -EINVAL;
630 		}
631 	}
632 
633 	/* root node if not have a parent */
634 	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
635 		/* check level */
636 		if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
637 		    level_id > IXGBE_TM_NODE_TYPE_PORT) {
638 			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
639 			error->message = "Wrong level";
640 			return -EINVAL;
641 		}
642 
643 		/* obviously no more than one root */
644 		if (tm_conf->root) {
645 			error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
646 			error->message = "already have a root";
647 			return -EINVAL;
648 		}
649 
650 		/* add the root node */
651 		tm_node = rte_zmalloc("ixgbe_tm_node",
652 				      sizeof(struct ixgbe_tm_node),
653 				      0);
654 		if (!tm_node)
655 			return -ENOMEM;
656 		tm_node->id = node_id;
657 		tm_node->priority = priority;
658 		tm_node->weight = weight;
659 		tm_node->reference_count = 0;
660 		tm_node->no = 0;
661 		tm_node->parent = NULL;
662 		tm_node->shaper_profile = shaper_profile;
663 		rte_memcpy(&tm_node->params, params,
664 				 sizeof(struct rte_tm_node_params));
665 		tm_conf->root = tm_node;
666 
667 		/* increase the reference counter of the shaper profile */
668 		if (shaper_profile)
669 			shaper_profile->reference_count++;
670 
671 		return 0;
672 	}
673 
674 	/* TC or queue node */
675 	/* check the parent node */
676 	parent_node = ixgbe_tm_node_search(dev, parent_node_id,
677 					   &parent_node_type);
678 	if (!parent_node) {
679 		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
680 		error->message = "parent not exist";
681 		return -EINVAL;
682 	}
683 	if (parent_node_type != IXGBE_TM_NODE_TYPE_PORT &&
684 	    parent_node_type != IXGBE_TM_NODE_TYPE_TC) {
685 		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
686 		error->message = "parent is not port or TC";
687 		return -EINVAL;
688 	}
689 	/* check level */
690 	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
691 	    level_id != parent_node_type + 1) {
692 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
693 		error->message = "Wrong level";
694 		return -EINVAL;
695 	}
696 
697 	/* check the node number */
698 	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
699 		/* check TC number */
700 		nb_tcs = ixgbe_tc_nb_get(dev);
701 		if (tm_conf->nb_tc_node >= nb_tcs) {
702 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
703 			error->message = "too many TCs";
704 			return -EINVAL;
705 		}
706 	} else {
707 		/* check queue number */
708 		if (tm_conf->nb_queue_node >= dev->data->nb_tx_queues) {
709 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
710 			error->message = "too many queues";
711 			return -EINVAL;
712 		}
713 
714 		ixgbe_queue_base_nb_get(dev, parent_node->no, &q_base, &q_nb);
715 		if (parent_node->reference_count >= q_nb) {
716 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
717 			error->message = "too many queues than TC supported";
718 			return -EINVAL;
719 		}
720 
721 		/**
722 		 * check the node id.
723 		 * For queue, the node id means queue id.
724 		 */
725 		if (node_id >= dev->data->nb_tx_queues) {
726 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
727 			error->message = "too large queue id";
728 			return -EINVAL;
729 		}
730 	}
731 
732 	/* add the TC or queue node */
733 	tm_node = rte_zmalloc("ixgbe_tm_node",
734 			      sizeof(struct ixgbe_tm_node),
735 			      0);
736 	if (!tm_node)
737 		return -ENOMEM;
738 	tm_node->id = node_id;
739 	tm_node->priority = priority;
740 	tm_node->weight = weight;
741 	tm_node->reference_count = 0;
742 	tm_node->parent = parent_node;
743 	tm_node->shaper_profile = shaper_profile;
744 	rte_memcpy(&tm_node->params, params,
745 			 sizeof(struct rte_tm_node_params));
746 	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
747 		tm_node->no = parent_node->reference_count;
748 		TAILQ_INSERT_TAIL(&tm_conf->tc_list,
749 				  tm_node, node);
750 		tm_conf->nb_tc_node++;
751 	} else {
752 		tm_node->no = q_base + parent_node->reference_count;
753 		TAILQ_INSERT_TAIL(&tm_conf->queue_list,
754 				  tm_node, node);
755 		tm_conf->nb_queue_node++;
756 	}
757 	tm_node->parent->reference_count++;
758 
759 	/* increase the reference counter of the shaper profile */
760 	if (shaper_profile)
761 		shaper_profile->reference_count++;
762 
763 	return 0;
764 }
765 
766 static int
767 ixgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
768 		  struct rte_tm_error *error)
769 {
770 	struct ixgbe_tm_conf *tm_conf =
771 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
772 	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
773 	struct ixgbe_tm_node *tm_node;
774 
775 	if (!error)
776 		return -EINVAL;
777 
778 	/* if already committed */
779 	if (tm_conf->committed) {
780 		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
781 		error->message = "already committed";
782 		return -EINVAL;
783 	}
784 
785 	if (node_id == RTE_TM_NODE_ID_NULL) {
786 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
787 		error->message = "invalid node id";
788 		return -EINVAL;
789 	}
790 
791 	/* check the if the node id exists */
792 	tm_node = ixgbe_tm_node_search(dev, node_id, &node_type);
793 	if (!tm_node) {
794 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
795 		error->message = "no such node";
796 		return -EINVAL;
797 	}
798 
799 	/* the node should have no child */
800 	if (tm_node->reference_count) {
801 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
802 		error->message =
803 			"cannot delete a node which has children";
804 		return -EINVAL;
805 	}
806 
807 	/* root node */
808 	if (node_type == IXGBE_TM_NODE_TYPE_PORT) {
809 		if (tm_node->shaper_profile)
810 			tm_node->shaper_profile->reference_count--;
811 		rte_free(tm_node);
812 		tm_conf->root = NULL;
813 		return 0;
814 	}
815 
816 	/* TC or queue node */
817 	if (tm_node->shaper_profile)
818 		tm_node->shaper_profile->reference_count--;
819 	tm_node->parent->reference_count--;
820 	if (node_type == IXGBE_TM_NODE_TYPE_TC) {
821 		TAILQ_REMOVE(&tm_conf->tc_list, tm_node, node);
822 		tm_conf->nb_tc_node--;
823 	} else {
824 		TAILQ_REMOVE(&tm_conf->queue_list, tm_node, node);
825 		tm_conf->nb_queue_node--;
826 	}
827 	rte_free(tm_node);
828 
829 	return 0;
830 }
831 
832 static int
833 ixgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
834 		    int *is_leaf, struct rte_tm_error *error)
835 {
836 	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
837 	struct ixgbe_tm_node *tm_node;
838 
839 	if (!is_leaf || !error)
840 		return -EINVAL;
841 
842 	if (node_id == RTE_TM_NODE_ID_NULL) {
843 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
844 		error->message = "invalid node id";
845 		return -EINVAL;
846 	}
847 
848 	/* check if the node id exists */
849 	tm_node = ixgbe_tm_node_search(dev, node_id, &node_type);
850 	if (!tm_node) {
851 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
852 		error->message = "no such node";
853 		return -EINVAL;
854 	}
855 
856 	if (node_type == IXGBE_TM_NODE_TYPE_QUEUE)
857 		*is_leaf = true;
858 	else
859 		*is_leaf = false;
860 
861 	return 0;
862 }
863 
864 static int
865 ixgbe_level_capabilities_get(struct rte_eth_dev *dev,
866 			     uint32_t level_id,
867 			     struct rte_tm_level_capabilities *cap,
868 			     struct rte_tm_error *error)
869 {
870 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
871 
872 	if (!cap || !error)
873 		return -EINVAL;
874 
875 	if (level_id >= IXGBE_TM_NODE_TYPE_MAX) {
876 		error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
877 		error->message = "too deep level";
878 		return -EINVAL;
879 	}
880 
881 	/* root node */
882 	if (level_id == IXGBE_TM_NODE_TYPE_PORT) {
883 		cap->n_nodes_max = 1;
884 		cap->n_nodes_nonleaf_max = 1;
885 		cap->n_nodes_leaf_max = 0;
886 	} else if (level_id == IXGBE_TM_NODE_TYPE_TC) {
887 		/* TC */
888 		cap->n_nodes_max = IXGBE_DCB_MAX_TRAFFIC_CLASS;
889 		cap->n_nodes_nonleaf_max = IXGBE_DCB_MAX_TRAFFIC_CLASS;
890 		cap->n_nodes_leaf_max = 0;
891 	} else {
892 		/* queue */
893 		cap->n_nodes_max = hw->mac.max_tx_queues;
894 		cap->n_nodes_nonleaf_max = 0;
895 		cap->n_nodes_leaf_max = hw->mac.max_tx_queues;
896 	}
897 
898 	cap->non_leaf_nodes_identical = true;
899 	cap->leaf_nodes_identical = true;
900 
901 	if (level_id != IXGBE_TM_NODE_TYPE_QUEUE) {
902 		cap->nonleaf.shaper_private_supported = true;
903 		cap->nonleaf.shaper_private_dual_rate_supported = false;
904 		cap->nonleaf.shaper_private_rate_min = 0;
905 		/* 10Gbps -> 1.25GBps */
906 		cap->nonleaf.shaper_private_rate_max = 1250000000ull;
907 		cap->nonleaf.shaper_shared_n_max = 0;
908 		if (level_id == IXGBE_TM_NODE_TYPE_PORT)
909 			cap->nonleaf.sched_n_children_max =
910 				IXGBE_DCB_MAX_TRAFFIC_CLASS;
911 		else
912 			cap->nonleaf.sched_n_children_max =
913 				hw->mac.max_tx_queues;
914 		cap->nonleaf.sched_sp_n_priorities_max = 1;
915 		cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
916 		cap->nonleaf.sched_wfq_n_groups_max = 0;
917 		cap->nonleaf.sched_wfq_weight_max = 1;
918 		cap->nonleaf.stats_mask = 0;
919 
920 		return 0;
921 	}
922 
923 	/* queue node */
924 	cap->leaf.shaper_private_supported = true;
925 	cap->leaf.shaper_private_dual_rate_supported = false;
926 	cap->leaf.shaper_private_rate_min = 0;
927 	/* 10Gbps -> 1.25GBps */
928 	cap->leaf.shaper_private_rate_max = 1250000000ull;
929 	cap->leaf.shaper_shared_n_max = 0;
930 	cap->leaf.cman_head_drop_supported = false;
931 	cap->leaf.cman_wred_context_private_supported = true;
932 	cap->leaf.cman_wred_context_shared_n_max = 0;
933 	cap->leaf.stats_mask = 0;
934 
935 	return 0;
936 }
937 
938 static int
939 ixgbe_node_capabilities_get(struct rte_eth_dev *dev,
940 			    uint32_t node_id,
941 			    struct rte_tm_node_capabilities *cap,
942 			    struct rte_tm_error *error)
943 {
944 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
945 	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
946 	struct ixgbe_tm_node *tm_node;
947 
948 	if (!cap || !error)
949 		return -EINVAL;
950 
951 	if (node_id == RTE_TM_NODE_ID_NULL) {
952 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
953 		error->message = "invalid node id";
954 		return -EINVAL;
955 	}
956 
957 	/* check if the node id exists */
958 	tm_node = ixgbe_tm_node_search(dev, node_id, &node_type);
959 	if (!tm_node) {
960 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
961 		error->message = "no such node";
962 		return -EINVAL;
963 	}
964 
965 	cap->shaper_private_supported = true;
966 	cap->shaper_private_dual_rate_supported = false;
967 	cap->shaper_private_rate_min = 0;
968 	/* 10Gbps -> 1.25GBps */
969 	cap->shaper_private_rate_max = 1250000000ull;
970 	cap->shaper_shared_n_max = 0;
971 
972 	if (node_type == IXGBE_TM_NODE_TYPE_QUEUE) {
973 		cap->leaf.cman_head_drop_supported = false;
974 		cap->leaf.cman_wred_context_private_supported = true;
975 		cap->leaf.cman_wred_context_shared_n_max = 0;
976 	} else {
977 		if (node_type == IXGBE_TM_NODE_TYPE_PORT)
978 			cap->nonleaf.sched_n_children_max =
979 				IXGBE_DCB_MAX_TRAFFIC_CLASS;
980 		else
981 			cap->nonleaf.sched_n_children_max =
982 				hw->mac.max_tx_queues;
983 		cap->nonleaf.sched_sp_n_priorities_max = 1;
984 		cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
985 		cap->nonleaf.sched_wfq_n_groups_max = 0;
986 		cap->nonleaf.sched_wfq_weight_max = 1;
987 	}
988 
989 	cap->stats_mask = 0;
990 
991 	return 0;
992 }
993 
994 static int
995 ixgbe_hierarchy_commit(struct rte_eth_dev *dev,
996 		       int clear_on_fail,
997 		       struct rte_tm_error *error)
998 {
999 	struct ixgbe_tm_conf *tm_conf =
1000 		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
1001 	struct ixgbe_tm_node *tm_node;
1002 	uint64_t bw;
1003 	int ret;
1004 
1005 	if (!error)
1006 		return -EINVAL;
1007 
1008 	/* check the setting */
1009 	if (!tm_conf->root)
1010 		goto done;
1011 
1012 	/* not support port max bandwidth yet */
1013 	if (tm_conf->root->shaper_profile &&
1014 	    tm_conf->root->shaper_profile->profile.peak.rate) {
1015 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1016 		error->message = "no port max bandwidth";
1017 		goto fail_clear;
1018 	}
1019 
1020 	/* HW not support TC max bandwidth */
1021 	TAILQ_FOREACH(tm_node, &tm_conf->tc_list, node) {
1022 		if (tm_node->shaper_profile &&
1023 		    tm_node->shaper_profile->profile.peak.rate) {
1024 			error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1025 			error->message = "no TC max bandwidth";
1026 			goto fail_clear;
1027 		}
1028 	}
1029 
1030 	/* queue max bandwidth */
1031 	TAILQ_FOREACH(tm_node, &tm_conf->queue_list, node) {
1032 		if (tm_node->shaper_profile)
1033 			bw = tm_node->shaper_profile->profile.peak.rate;
1034 		else
1035 			bw = 0;
1036 		if (bw) {
1037 			/* interpret Bps to Mbps */
1038 			bw = bw * 8 / 1000 / 1000;
1039 			ret = ixgbe_set_queue_rate_limit(dev, tm_node->no, bw);
1040 			if (ret) {
1041 				error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1042 				error->message =
1043 					"failed to set queue max bandwidth";
1044 				goto fail_clear;
1045 			}
1046 		}
1047 	}
1048 
1049 done:
1050 	tm_conf->committed = true;
1051 	return 0;
1052 
1053 fail_clear:
1054 	/* clear all the traffic manager configuration */
1055 	if (clear_on_fail) {
1056 		ixgbe_tm_conf_uninit(dev);
1057 		ixgbe_tm_conf_init(dev);
1058 	}
1059 	return -EINVAL;
1060 }
1061