diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index ca1de9f..9097456 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -342,6 +342,16 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		enum TCA_FLOWER_KEY_VLAN_ETH_TYPE \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_TCA_FLOWER_KEY_TCP_FLAGS \
+		linux/pkt_cls.h \
+		enum TCA_FLOWER_KEY_TCP_FLAGS \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
+		HAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK \
+		linux/pkt_cls.h \
+		enum TCA_FLOWER_KEY_TCP_FLAGS_MASK \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_TC_ACT_VLAN \
 		linux/tc_act/tc_vlan.h \
 		enum TCA_VLAN_PUSH_VLAN_PRIORITY \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index fd93ac1..f562f30 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -180,6 +180,10 @@ if build
 		'TCA_FLOWER_KEY_VLAN_PRIO' ],
 		[ 'HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE', 'linux/pkt_cls.h',
 		'TCA_FLOWER_KEY_VLAN_ETH_TYPE' ],
+		[ 'HAVE_TCA_FLOWER_KEY_TCP_FLAGS', 'linux/pkt_cls.h',
+		'TCA_FLOWER_KEY_TCP_FLAGS' ],
+		[ 'HAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK', 'linux/pkt_cls.h',
+		'TCA_FLOWER_KEY_TCP_FLAGS_MASK' ],
 		[ 'HAVE_TC_ACT_VLAN', 'linux/tc_act/tc_vlan.h',
 		'TCA_VLAN_PUSH_VLAN_PRIORITY' ],
 		[ 'HAVE_RDMA_NL_NLDEV', 'rdma/rdma_netlink.h',
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index ed60c40..a794a91 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -1226,6 +1226,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *   Bit-fields that holds the items detected until now.
  * @param[in] target_protocol
  *   The next protocol in the previous item.
+ * @param[in] flow_mask
+ *   mlx5 flow-specific (TCF, DV, verbs, etc.) supported header fields mask.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -1236,12 +1238,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 			    uint64_t item_flags,
 			    uint8_t target_protocol,
+			    const struct rte_flow_item_tcp *flow_mask,
 			    struct rte_flow_error *error)
 {
 	const struct rte_flow_item_tcp *mask = item->mask;
 	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
 	int ret;
 
+	assert(flow_mask);
 	if (target_protocol != 0xff && target_protocol != IPPROTO_TCP)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1261,7 +1265,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		mask = &rte_flow_item_tcp_mask;
 	ret = mlx5_flow_item_acceptable
 		(item, (const uint8_t *)mask,
-		 (const uint8_t *)&rte_flow_item_tcp_mask,
+		 (const uint8_t *)flow_mask,
 		 sizeof(struct rte_flow_item_tcp), error);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 12de841..dbe3f84 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -314,6 +314,7 @@ int mlx5_flow_validate_item_mpls(const struct rte_flow_item *item,
 int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
+				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 3bb462c..a824b19 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -179,8 +179,11 @@
 					       MLX5_FLOW_LAYER_OUTER_L4_UDP;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			ret = mlx5_flow_validate_item_tcp(items, item_flags,
-							  next_protocol, error);
+			ret = mlx5_flow_validate_item_tcp
+						(items, item_flags,
+						 next_protocol,
+						 &rte_flow_item_tcp_mask,
+						 error);
 			if (ret < 0)
 				return ret;
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c
index 91f6ef6..cc0f66c 100644
--- a/drivers/net/mlx5/mlx5_flow_tcf.c
+++ b/drivers/net/mlx5/mlx5_flow_tcf.c
@@ -148,6 +148,12 @@ struct tc_vlan {
 #ifndef HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE
 #define TCA_FLOWER_KEY_VLAN_ETH_TYPE 25
 #endif
+#ifndef HAVE_TCA_FLOWER_KEY_TCP_FLAGS
+#define TCA_FLOWER_KEY_TCP_FLAGS 71
+#endif
+#ifndef HAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK
+#define TCA_FLOWER_KEY_TCP_FLAGS_MASK 72
+#endif
 
 #ifndef IPV6_ADDR_LEN
 #define IPV6_ADDR_LEN 16
@@ -204,6 +210,7 @@ struct tc_vlan {
 	.tcp.hdr = {
 		.src_port = RTE_BE16(0xffff),
 		.dst_port = RTE_BE16(0xffff),
+		.tcp_flags = 0xff,
 	},
 	.udp.hdr = {
 		.src_port = RTE_BE16(0xffff),
@@ -626,13 +633,16 @@ struct flow_tcf_ptoi {
 				return -rte_errno;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			ret = mlx5_flow_validate_item_tcp(items, item_flags,
-							  next_protocol, error);
+			ret = mlx5_flow_validate_item_tcp
+					     (items, item_flags,
+					      next_protocol,
+					      &flow_tcf_mask_supported.tcp,
+					      error);
 			if (ret < 0)
 				return ret;
 			item_flags |= MLX5_FLOW_LAYER_OUTER_L4_TCP;
 			mask.tcp = flow_tcf_item_mask
-				(items, &rte_flow_item_tcp_mask,
+				(items, &flow_tcf_mask_supported.tcp,
 				 &flow_tcf_mask_supported.tcp,
 				 &flow_tcf_mask_empty.tcp,
 				 sizeof(flow_tcf_mask_supported.tcp),
@@ -1289,6 +1299,18 @@ struct flow_tcf_ptoi {
 						 TCA_FLOWER_KEY_TCP_DST_MASK,
 						 mask.tcp->hdr.dst_port);
 			}
+			if (mask.tcp->hdr.tcp_flags) {
+				mnl_attr_put_u16
+					(nlh,
+					 TCA_FLOWER_KEY_TCP_FLAGS,
+					 rte_cpu_to_be_16
+						(spec.tcp->hdr.tcp_flags));
+				mnl_attr_put_u16
+					(nlh,
+					 TCA_FLOWER_KEY_TCP_FLAGS_MASK,
+					 rte_cpu_to_be_16
+						(mask.tcp->hdr.tcp_flags));
+			}
 			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 6964476..26bcc85 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1056,8 +1056,11 @@
 					       MLX5_FLOW_LAYER_OUTER_L4_UDP;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
-			ret = mlx5_flow_validate_item_tcp(items, item_flags,
-							  next_protocol, error);
+			ret = mlx5_flow_validate_item_tcp
+						(items, item_flags,
+						 next_protocol,
+						 &rte_flow_item_tcp_mask,
+						 error);
 			if (ret < 0)
 				return ret;
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
