src/dpdk/drivers/net/ixgbe/ixgbe_tm.c
static int
ixgbe_node_add(struct rte_eth_dev *dev, 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)
{
	struct ixgbe_tm_conf *tm_conf =
		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
	enum ixgbe_tm_node_type parent_node_type = IXGBE_TM_NODE_TYPE_MAX;
	struct ixgbe_tm_shaper_profile *shaper_profile = NULL;
	struct ixgbe_tm_node *tm_node;
	struct ixgbe_tm_node *parent_node;
	uint8_t nb_tcs;
	uint16_t q_base = 0;
	uint16_t q_nb = 0;
	int ret;

	if (!params || !error)
		return -EINVAL;

	/* if already committed */
	if (tm_conf->committed) {
		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
		error->message = "already committed";
		return -EINVAL;
	}

	ret = ixgbe_node_param_check(dev, node_id, priority, weight,
				     params, error);
	if (ret)
		return ret;

	/* check if the node ID is already used */
	if (ixgbe_tm_node_search(dev, node_id, &node_type)) {
		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
		error->message = "node id already used";
		return -EINVAL;
	}

	/* check the shaper profile id */
	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
		shaper_profile = ixgbe_shaper_profile_search(
					dev, params->shaper_profile_id);
		if (!shaper_profile) {
			error->type =
				RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
			error->message = "shaper profile not exist";
			return -EINVAL;
		}
	}

	/* root node if not have a parent */
	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
		/* check level */
		if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
		    level_id > IXGBE_TM_NODE_TYPE_PORT) {
			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
			error->message = "Wrong level";
			return -EINVAL;
		}

		/* obviously no more than one root */
		if (tm_conf->root) {
			error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
			error->message = "already have a root";
			return -EINVAL;
		}

		/* add the root node */
		tm_node = rte_zmalloc("ixgbe_tm_node",
				      sizeof(struct ixgbe_tm_node),
				      0);
		if (!tm_node)
			return -ENOMEM;
		tm_node->id = node_id;
		tm_node->priority = priority;
		tm_node->weight = weight;
		tm_node->reference_count = 0;
		tm_node->no = 0;
		tm_node->parent = NULL;
		tm_node->shaper_profile = shaper_profile;
		rte_memcpy(&tm_node->params, params,
				 sizeof(struct rte_tm_node_params));
		tm_conf->root = tm_node;

		/* increase the reference counter of the shaper profile */
		if (shaper_profile)
			shaper_profile->reference_count++;

		return 0;
	}

	/* TC or queue node */
	/* check the parent node */
	parent_node = ixgbe_tm_node_search(dev, parent_node_id,
					   &parent_node_type);
	if (!parent_node) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
		error->message = "parent not exist";
		return -EINVAL;
	}
	if (parent_node_type != IXGBE_TM_NODE_TYPE_PORT &&
	    parent_node_type != IXGBE_TM_NODE_TYPE_TC) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
		error->message = "parent is not port or TC";
		return -EINVAL;
	}
	/* check level */
	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
	    level_id != parent_node_type + 1) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
		error->message = "Wrong level";
		return -EINVAL;
	}

	/* check the node number */
	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
		/* check TC number */
		nb_tcs = ixgbe_tc_nb_get(dev);
		if (tm_conf->nb_tc_node >= nb_tcs) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many TCs";
			return -EINVAL;
		}
	} else {
		/* check queue number */
		if (tm_conf->nb_queue_node >= dev->data->nb_tx_queues) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many queues";
			return -EINVAL;
		}

		ixgbe_queue_base_nb_get(dev, parent_node->no, &q_base, &q_nb);
		if (parent_node->reference_count >= q_nb) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many queues than TC supported";
			return -EINVAL;
		}

		/**
		 * check the node id.
		 * For queue, the node id means queue id.
		 */
		if (node_id >= dev->data->nb_tx_queues) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too large queue id";
			return -EINVAL;
		}
	}

	/* add the TC or queue node */
	tm_node = rte_zmalloc("ixgbe_tm_node",
			      sizeof(struct ixgbe_tm_node),
			      0);
	if (!tm_node)
		return -ENOMEM;
	tm_node->id = node_id;
	tm_node->priority = priority;
	tm_node->weight = weight;
	tm_node->reference_count = 0;
	tm_node->parent = parent_node;
	tm_node->shaper_profile = shaper_profile;
	rte_memcpy(&tm_node->params, params,
			 sizeof(struct rte_tm_node_params));
	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
		tm_node->no = parent_node->reference_count;
		TAILQ_INSERT_TAIL(&tm_conf->tc_list,
				  tm_node, node);
		tm_conf->nb_tc_node++;
	} else {
		tm_node->no = q_base + parent_node->reference_count;
		TAILQ_INSERT_TAIL(&tm_conf->queue_list,
				  tm_node, node);
		tm_conf->nb_queue_node++;
	}
	tm_node->parent->reference_count++;

	/* increase the reference counter of the shaper profile */
	if (shaper_profile)
		shaper_profile->reference_count++;

	return 0;
}
/**
 * Now the TC and queue configuration is controlled by DCB.
 * We need check if the node configuration follows the DCB configuration.
 * In the future, we may use TM to cover DCB.
 */
Now the TC and queue configuration is controlled by DCB.
We need check if the node configuration follows the DCB configuration.
In the future, we may use TM to cover DCB.
Now the TC and queue configuration is controlled by DCB . We need check if the node configuration follows the DCB configuration . In the future we may use TM to cover DCB .
static int
ixgbe_node_add(struct rte_eth_dev *dev, 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)
{
	struct ixgbe_tm_conf *tm_conf =
		IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
	enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX;
	enum ixgbe_tm_node_type parent_node_type = IXGBE_TM_NODE_TYPE_MAX;
	struct ixgbe_tm_shaper_profile *shaper_profile = NULL;
	struct ixgbe_tm_node *tm_node;
	struct ixgbe_tm_node *parent_node;
	uint8_t nb_tcs;
	uint16_t q_base = 0;
	uint16_t q_nb = 0;
	int ret;
	if (!params || !error)
		return -EINVAL;
	if (tm_conf->committed) {
		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
		error->message = "already committed";
		return -EINVAL;
	}
	ret = ixgbe_node_param_check(dev, node_id, priority, weight,
				     params, error);
	if (ret)
		return ret;
	if (ixgbe_tm_node_search(dev, node_id, &node_type)) {
		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
		error->message = "node id already used";
		return -EINVAL;
	}
	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
		shaper_profile = ixgbe_shaper_profile_search(
					dev, params->shaper_profile_id);
		if (!shaper_profile) {
			error->type =
				RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
			error->message = "shaper profile not exist";
			return -EINVAL;
		}
	}
	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
		if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
		    level_id > IXGBE_TM_NODE_TYPE_PORT) {
			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
			error->message = "Wrong level";
			return -EINVAL;
		}
		if (tm_conf->root) {
			error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
			error->message = "already have a root";
			return -EINVAL;
		}
		tm_node = rte_zmalloc("ixgbe_tm_node",
				      sizeof(struct ixgbe_tm_node),
				      0);
		if (!tm_node)
			return -ENOMEM;
		tm_node->id = node_id;
		tm_node->priority = priority;
		tm_node->weight = weight;
		tm_node->reference_count = 0;
		tm_node->no = 0;
		tm_node->parent = NULL;
		tm_node->shaper_profile = shaper_profile;
		rte_memcpy(&tm_node->params, params,
				 sizeof(struct rte_tm_node_params));
		tm_conf->root = tm_node;
		if (shaper_profile)
			shaper_profile->reference_count++;
		return 0;
	}
	parent_node = ixgbe_tm_node_search(dev, parent_node_id,
					   &parent_node_type);
	if (!parent_node) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
		error->message = "parent not exist";
		return -EINVAL;
	}
	if (parent_node_type != IXGBE_TM_NODE_TYPE_PORT &&
	    parent_node_type != IXGBE_TM_NODE_TYPE_TC) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
		error->message = "parent is not port or TC";
		return -EINVAL;
	}
	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
	    level_id != parent_node_type + 1) {
		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
		error->message = "Wrong level";
		return -EINVAL;
	}
	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
		nb_tcs = ixgbe_tc_nb_get(dev);
		if (tm_conf->nb_tc_node >= nb_tcs) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many TCs";
			return -EINVAL;
		}
	} else {
		if (tm_conf->nb_queue_node >= dev->data->nb_tx_queues) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many queues";
			return -EINVAL;
		}
		ixgbe_queue_base_nb_get(dev, parent_node->no, &q_base, &q_nb);
		if (parent_node->reference_count >= q_nb) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too many queues than TC supported";
			return -EINVAL;
		}
		if (node_id >= dev->data->nb_tx_queues) {
			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
			error->message = "too large queue id";
			return -EINVAL;
		}
	}
	tm_node = rte_zmalloc("ixgbe_tm_node",
			      sizeof(struct ixgbe_tm_node),
			      0);
	if (!tm_node)
		return -ENOMEM;
	tm_node->id = node_id;
	tm_node->priority = priority;
	tm_node->weight = weight;
	tm_node->reference_count = 0;
	tm_node->parent = parent_node;
	tm_node->shaper_profile = shaper_profile;
	rte_memcpy(&tm_node->params, params,
			 sizeof(struct rte_tm_node_params));
	if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) {
		tm_node->no = parent_node->reference_count;
		TAILQ_INSERT_TAIL(&tm_conf->tc_list,
				  tm_node, node);
		tm_conf->nb_tc_node++;
	} else {
		tm_node->no = q_base + parent_node->reference_count;
		TAILQ_INSERT_TAIL(&tm_conf->queue_list,
				  tm_node, node);
		tm_conf->nb_queue_node++;
	}
	tm_node->parent->reference_count++;
	if (shaper_profile)
		shaper_profile->reference_count++;
	return 0;
}
static int ixgbe_node_add ( struct rte_eth_dev * dev , 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 ) { struct ixgbe_tm_conf * tm_conf = IXGBE_DEV_PRIVATE_TO_TM_CONF ( dev -> data -> dev_private ) ; enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX ; enum ixgbe_tm_node_type parent_node_type = IXGBE_TM_NODE_TYPE_MAX ; struct ixgbe_tm_shaper_profile * shaper_profile = NULL ; struct ixgbe_tm_node * tm_node ; struct ixgbe_tm_node * parent_node ; uint8_t nb_tcs ; uint16_t q_base = 0 ; uint16_t q_nb = 0 ; int ret ; if ( ! params || ! error ) return - EINVAL ; if ( tm_conf -> committed ) { error -> type = RTE_TM_ERROR_TYPE_UNSPECIFIED ; error -> message = " " ; return - EINVAL ; } ret = ixgbe_node_param_check ( dev , node_id , priority , weight , params , error ) ; if ( ret ) return ret ; if ( ixgbe_tm_node_search ( dev , node_id , & node_type ) ) { error -> type = RTE_TM_ERROR_TYPE_NODE_ID ; error -> message = " " ; return - EINVAL ; } if ( params -> shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE ) { shaper_profile = ixgbe_shaper_profile_search ( dev , params -> shaper_profile_id ) ; if ( ! shaper_profile ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID ; error -> message = " " ; return - EINVAL ; } } if ( parent_node_id == RTE_TM_NODE_ID_NULL ) { if ( level_id != RTE_TM_NODE_LEVEL_ID_ANY && level_id > IXGBE_TM_NODE_TYPE_PORT ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARAMS ; error -> message = " " ; return - EINVAL ; } if ( tm_conf -> root ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID ; error -> message = " " ; return - EINVAL ; } tm_node = rte_zmalloc ( " " , sizeof ( struct ixgbe_tm_node ) , 0 ) ; if ( ! tm_node ) return - ENOMEM ; tm_node -> id = node_id ; tm_node -> priority = priority ; tm_node -> weight = weight ; tm_node -> reference_count = 0 ; tm_node -> no = 0 ; tm_node -> parent = NULL ; tm_node -> shaper_profile = shaper_profile ; rte_memcpy ( & tm_node -> params , params , sizeof ( struct rte_tm_node_params ) ) ; tm_conf -> root = tm_node ; if ( shaper_profile ) shaper_profile -> reference_count ++ ; return 0 ; } parent_node = ixgbe_tm_node_search ( dev , parent_node_id , & parent_node_type ) ; if ( ! parent_node ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID ; error -> message = " " ; return - EINVAL ; } if ( parent_node_type != IXGBE_TM_NODE_TYPE_PORT && parent_node_type != IXGBE_TM_NODE_TYPE_TC ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID ; error -> message = " " ; return - EINVAL ; } if ( level_id != RTE_TM_NODE_LEVEL_ID_ANY && level_id != parent_node_type + 1 ) { error -> type = RTE_TM_ERROR_TYPE_NODE_PARAMS ; error -> message = " " ; return - EINVAL ; } if ( parent_node_type == IXGBE_TM_NODE_TYPE_PORT ) { nb_tcs = ixgbe_tc_nb_get ( dev ) ; if ( tm_conf -> nb_tc_node >= nb_tcs ) { error -> type = RTE_TM_ERROR_TYPE_NODE_ID ; error -> message = " " ; return - EINVAL ; } } else { if ( tm_conf -> nb_queue_node >= dev -> data -> nb_tx_queues ) { error -> type = RTE_TM_ERROR_TYPE_NODE_ID ; error -> message = " " ; return - EINVAL ; } ixgbe_queue_base_nb_get ( dev , parent_node -> no , & q_base , & q_nb ) ; if ( parent_node -> reference_count >= q_nb ) { error -> type = RTE_TM_ERROR_TYPE_NODE_ID ; error -> message = " " ; return - EINVAL ; } if ( node_id >= dev -> data -> nb_tx_queues ) { error -> type = RTE_TM_ERROR_TYPE_NODE_ID ; error -> message = " " ; return - EINVAL ; } } tm_node = rte_zmalloc ( " " , sizeof ( struct ixgbe_tm_node ) , 0 ) ; if ( ! tm_node ) return - ENOMEM ; tm_node -> id = node_id ; tm_node -> priority = priority ; tm_node -> weight = weight ; tm_node -> reference_count = 0 ; tm_node -> parent = parent_node ; tm_node -> shaper_profile = shaper_profile ; rte_memcpy ( & tm_node -> params , params , sizeof ( struct rte_tm_node_params ) ) ; if ( parent_node_type == IXGBE_TM_NODE_TYPE_PORT ) { tm_node -> no = parent_node -> reference_count ; TAILQ_INSERT_TAIL ( & tm_conf -> tc_list , tm_node , node ) ; tm_conf -> nb_tc_node ++ ; } else { tm_node -> no = q_base + parent_node -> reference_count ; TAILQ_INSERT_TAIL ( & tm_conf -> queue_list , tm_node , node ) ; tm_conf -> nb_queue_node ++ ; } tm_node -> parent -> reference_count ++ ; if ( shaper_profile ) shaper_profile -> reference_count ++ ; return 0 ; }
Now the TC and queue configuration is controlled by DCB.
Now the TC and queue configuration is controlled by DCB .
/* if already committed */ /* check if the node ID is already used */ /* check the shaper profile id */ /* root node if not have a parent */ /* check level */ /* obviously no more than one root */ /* add the root node */ /* increase the reference counter of the shaper profile */ /* TC or queue node */ /* check the parent node */ /* check level */ /* check the node number */ /* check TC number */ /* check queue number */ /**
		 * check the node id.
		 * For queue, the node id means queue id.
		 */ /* add the TC or queue node */ /* increase the reference counter of the shaper profile */