+ fm = next_fm;
+ } while (fm);
+ /* Create tag color rules for all needed fms. */
+ for (i = 0; i < fm_cnt; i++) {
+ void *mtr_action;
+
+ mtr_policy = fm_info[i].fm_policy;
+ rte_spinlock_lock(&mtr_policy->sl);
+ sub_policy = mtr_policy->sub_policys[domain][0];
+ for (j = 0; j < MLX5_MTR_RTE_COLORS; j++) {
+ if (mtr_policy->act_cnt[j].fate_action != MLX5_FLOW_FATE_MTR)
+ continue;
+ color_rule = mlx5_malloc(MLX5_MEM_ZERO,
+ sizeof(struct mlx5_sub_policy_color_rule),
+ 0, SOCKET_ID_ANY);
+ if (!color_rule) {
+ rte_spinlock_unlock(&mtr_policy->sl);
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "No memory to create tag color rule.");
+ goto err_exit;
+ }
+ color_rule->src_port = src_port;
+ next_fm = fm_info[i].next_fm;
+ if (mlx5_flow_meter_attach(priv, next_fm, &attr, error)) {
+ mlx5_free(color_rule);
+ rte_spinlock_unlock(&mtr_policy->sl);
+ goto err_exit;
+ }
+ fm_info[i].tag_rule[j] = color_rule;
+ TAILQ_INSERT_TAIL(&sub_policy->color_rules[j], color_rule, next_port);
+ /* Prepare to create color rule. */
+ mtr_action = (next_fm->color_aware && j == RTE_COLOR_YELLOW) ?
+ next_fm->meter_action_y :
+ next_fm->meter_action_g;
+ next_policy = mlx5_flow_meter_policy_find(dev, next_fm->policy_id, NULL);
+ MLX5_ASSERT(next_policy);
+ next_sub_policy = next_policy->sub_policys[domain][0];
+ tbl_data = container_of(next_sub_policy->tbl_rsc,
+ struct mlx5_flow_tbl_data_entry, tbl);
+ if (mtr_first) {
+ acts.dv_actions[0] = mtr_action;
+ acts.dv_actions[1] = mtr_policy->act_cnt[j].modify_hdr->action;
+ } else {
+ acts.dv_actions[0] = mtr_policy->act_cnt[j].modify_hdr->action;
+ acts.dv_actions[1] = mtr_action;
+ }
+ acts.dv_actions[2] = tbl_data->jump.action;
+ acts.actions_n = 3;
+ if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
+ MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
+ &attr, true, item, &color_rule->matcher, error)) {
+ rte_spinlock_unlock(&mtr_policy->sl);
+ rte_flow_error_set(error, errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to create hierarchy meter matcher.");
+ goto err_exit;
+ }
+ if (__flow_dv_create_policy_flow(dev, color_reg_c_idx, (enum rte_color)j,
+ color_rule->matcher->matcher_object,
+ acts.actions_n, acts.dv_actions,
+ true, item, &color_rule->rule, &attr)) {
+ rte_spinlock_unlock(&mtr_policy->sl);
+ rte_flow_error_set(error, errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to create hierarchy meter rule.");
+ goto err_exit;
+ }