- /* First step. Validate the attributes, items and actions. */
- *parser = (struct mlx5_flow_parse){
- .create = parser->create,
- .layer = HASH_RXQ_ETH,
- .mark_id = MLX5_FLOW_MARK_DEFAULT,
- };
- ret = priv_flow_convert_attributes(priv, attr, error, parser);
- if (ret)
- return ret;
- ret = priv_flow_convert_actions(priv, actions, error, parser);
- if (ret)
- return ret;
- ret = priv_flow_convert_items_validate(priv, items, error, parser);
- if (ret)
- return ret;
- priv_flow_convert_finalise(priv, parser);
- /*
- * Second step.
- * Allocate the memory space to store verbs specifications.
- */
- if (parser->drop) {
- unsigned int priority =
- attr->priority +
- hash_rxq_init[HASH_RXQ_ETH].flow_priority;
- unsigned int offset = parser->queue[HASH_RXQ_ETH].offset;
-
- parser->queue[HASH_RXQ_ETH].ibv_attr =
- priv_flow_convert_allocate(priv, priority,
- offset, error);
- if (!parser->queue[HASH_RXQ_ETH].ibv_attr)
- return ENOMEM;
- parser->queue[HASH_RXQ_ETH].offset =
- sizeof(struct ibv_flow_attr);
- } else {
- for (i = 0; i != hash_rxq_init_n; ++i) {
- unsigned int priority =
- attr->priority +
- hash_rxq_init[i].flow_priority;
- unsigned int offset;
-
- if (!(parser->rss_conf.rss_hf &
- hash_rxq_init[i].dpdk_rss_hf) &&
- (i != HASH_RXQ_ETH))
- continue;
- offset = parser->queue[i].offset;
- parser->queue[i].ibv_attr =
- priv_flow_convert_allocate(priv, priority,
- offset, error);
- if (!parser->queue[i].ibv_attr)
- goto exit_enomem;
- parser->queue[i].offset = sizeof(struct ibv_flow_attr);
- }
- }
- /* Third step. Conversion parse, fill the specifications. */
- parser->inner = 0;
- for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
- if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
- continue;
- cur_item = &mlx5_flow_items[items->type];
- ret = cur_item->convert(items,
- (cur_item->default_mask ?
- cur_item->default_mask :
- cur_item->mask),
- parser);
- if (ret) {
- rte_flow_error_set(error, ret,
- RTE_FLOW_ERROR_TYPE_ITEM,
- items, "item not supported");
- goto exit_free;
- }
- }
- if (parser->mark)
- mlx5_flow_create_flag_mark(parser, parser->mark_id);
- if (parser->count && parser->create) {
- mlx5_flow_create_count(priv, parser);
- if (!parser->cs)
- goto exit_count_error;
- }
- /*
- * Last step. Complete missing specification to reach the RSS
- * configuration.
- */
- if (!parser->drop) {
- priv_flow_convert_finalise(priv, parser);
- } else {
- parser->queue[HASH_RXQ_ETH].ibv_attr->priority =
- attr->priority +
- hash_rxq_init[parser->layer].flow_priority;
- }
- if (parser->allmulti &&
- parser->layer == HASH_RXQ_ETH) {
- for (i = 0; i != hash_rxq_init_n; ++i) {
- if (!parser->queue[i].ibv_attr)
- continue;
- if (parser->queue[i].ibv_attr->num_of_specs != 1)
- break;
- parser->queue[i].ibv_attr->type =
- IBV_FLOW_ATTR_MC_DEFAULT;
- }
- }
-exit_free:
- /* Only verification is expected, all resources should be released. */
- if (!parser->create) {
- for (i = 0; i != hash_rxq_init_n; ++i) {
- if (parser->queue[i].ibv_attr) {
- rte_free(parser->queue[i].ibv_attr);
- parser->queue[i].ibv_attr = NULL;
- }
- }
- }
- return ret;
-exit_enomem:
- for (i = 0; i != hash_rxq_init_n; ++i) {
- if (parser->queue[i].ibv_attr) {
- rte_free(parser->queue[i].ibv_attr);
- parser->queue[i].ibv_attr = NULL;
- }
- }
- rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "cannot allocate verbs spec attributes.");
- return ret;
-exit_count_error:
- rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "cannot create counter.");
- return rte_errno;