+ * Create flow item template.
+ *
+ * @param[in] dev
+ * Pointer to the rte_eth_dev structure.
+ * @param[in] attr
+ * Pointer to the item template attributes.
+ * @param[in] items
+ * The template item pattern.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * Item template pointer on success, NULL otherwise and rte_errno is set.
+ */
+static struct rte_flow_pattern_template *
+flow_hw_pattern_template_create(struct rte_eth_dev *dev,
+ const struct rte_flow_pattern_template_attr *attr,
+ const struct rte_flow_item items[],
+ struct rte_flow_error *error)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct rte_flow_pattern_template *it;
+
+ it = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*it), 0, rte_socket_id());
+ if (!it) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "cannot allocate item template");
+ return NULL;
+ }
+ it->attr = *attr;
+ it->mt = mlx5dr_match_template_create(items, attr->relaxed_matching);
+ if (!it->mt) {
+ mlx5_free(it);
+ rte_flow_error_set(error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "cannot create match template");
+ return NULL;
+ }
+ __atomic_fetch_add(&it->refcnt, 1, __ATOMIC_RELAXED);
+ LIST_INSERT_HEAD(&priv->flow_hw_itt, it, next);
+ return it;
+}
+
+/**
+ * Destroy flow item template.
+ *
+ * @param[in] dev
+ * Pointer to the rte_eth_dev structure.
+ * @param[in] template
+ * Pointer to the item template to be destroyed.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_hw_pattern_template_destroy(struct rte_eth_dev *dev __rte_unused,
+ struct rte_flow_pattern_template *template,
+ struct rte_flow_error *error __rte_unused)
+{
+ if (__atomic_load_n(&template->refcnt, __ATOMIC_RELAXED) > 1) {
+ DRV_LOG(WARNING, "Item template %p is still in use.",
+ (void *)template);
+ return rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "item template in using");
+ }
+ LIST_REMOVE(template, next);
+ claim_zero(mlx5dr_match_template_destroy(template->mt));
+ mlx5_free(template);
+ return 0;
+}
+
+/*