diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 99d3c40f36..514903dbe1 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1526,6 +1526,7 @@ flow_hw_get_reg_id(enum rte_flow_item_type type, uint32_t id)
 		 */
 		return REG_A;
 	case RTE_FLOW_ITEM_TYPE_CONNTRACK:
+	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
 		return mlx5_flow_hw_aso_tag;
 	case RTE_FLOW_ITEM_TYPE_TAG:
 		MLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index e1db68b532..0785734217 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1387,6 +1387,7 @@ mlx5_flow_item_field_width(struct rte_eth_dev *dev,
 		return inherit < 0 ? 0 : inherit;
 	case RTE_FLOW_FIELD_IPV4_ECN:
 	case RTE_FLOW_FIELD_IPV6_ECN:
+	case RTE_FLOW_FIELD_METER_COLOR
 		return 2;
 	default:
 		MLX5_ASSERT(false);
@@ -1846,6 +1847,31 @@ mlx5_flow_field_id_to_modify_info
 				info[idx].offset = data->offset;
 		}
 		break;
+	case RTE_FLOW_FIELD_METER_COLOR:
+		{
+			const uint32_t color_mask =
+				(UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
+			int reg;
+
+			if (priv->sh->config.dv_flow_en == 2)
+				reg = flow_hw_get_reg_id
+					(RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
+			else
+				reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
+						       0, error);
+			if (reg < 0)
+				return;
+			MLX5_ASSERT(reg != REG_NON);
+			MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
+			info[idx] = (struct field_modify_info){4, 0,
+						reg_to_field[reg]};
+			if (mask)
+				mask[idx] = flow_modify_info_mask_32_masked
+					(width, data->offset, color_mask);
+			else
+				info[idx].offset = data->offset;
+		}
+		break;
 	case RTE_FLOW_FIELD_POINTER:
 	case RTE_FLOW_FIELD_VALUE:
 	default:
@@ -1893,7 +1919,7 @@ flow_dv_convert_action_modify_field
 	uint32_t type, meta = 0;
 
 	if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
-	    conf->src.field == RTE_FLOW_FIELD_VALUE) {
+	    conf->src.field == RTE_FLOW_FIELD_VALUE) {/
 		type = MLX5_MODIFICATION_TYPE_SET;
 		/** For SET fill the destination field (field) first. */
 		mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,
@@ -1902,7 +1928,9 @@ flow_dv_convert_action_modify_field
 		item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ?
 					(void *)(uintptr_t)conf->src.pvalue :
 					(void *)(uintptr_t)&conf->src.value;
-		if (conf->dst.field == RTE_FLOW_FIELD_META) {
+		if (conf->dst.field == RTE_FLOW_FIELD_META ||
+		    conf->dst.field == RTE_FLOW_FIELD_TAG ||
+		    conf->dst.field == RTE_FLOW_FIELD_METER_COLOR) {
 			meta = *(const unaligned_uint32_t *)item.spec;
 			meta = rte_cpu_to_be_32(meta);
 			item.spec = &meta;
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 7e7b48f884..87b3e34cb4 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -870,6 +870,7 @@ flow_hw_modify_field_compile(struct rte_eth_dev *dev,
 				(void *)(uintptr_t)&conf->src.value;
 		if (conf->dst.field == RTE_FLOW_FIELD_META ||
 		    conf->dst.field == RTE_FLOW_FIELD_TAG ||
+		    conf->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
 		    conf->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
 			value = *(const unaligned_uint32_t *)item.spec;
 			value = rte_cpu_to_be_32(value);
@@ -1702,6 +1703,7 @@ flow_hw_modify_field_construct(struct mlx5_hw_q_job *job,
 		rte_memcpy(values, mhdr_action->src.pvalue, sizeof(values));
 	if (mhdr_action->dst.field == RTE_FLOW_FIELD_META ||
 	    mhdr_action->dst.field == RTE_FLOW_FIELD_TAG ||
+	    mhdr_action->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
 	    mhdr_action->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
 		value_p = (unaligned_uint32_t *)values;
 		*value_p = rte_cpu_to_be_32(*value_p);
@@ -3704,6 +3706,16 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 								  " attribute");
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_METER_COLOR:
+		{
+			int reg = flow_hw_get_reg_id(RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
+			if (reg == REG_NON)
+				return rte_flow_error_set(error, EINVAL,
+							  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+							  NULL,
+							  "Unsupported meter color register");
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
