diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 3070e0e..d10f511 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -181,6 +181,9 @@ enum index {
 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
 	ITEM_META,
 	ITEM_META_DATA,
+	ITEM_METADATA,
+	ITEM_METADATA_ID,
+	ITEM_METADATA_DATA,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -272,6 +275,9 @@ enum index {
 	ACTION_SET_MAC_SRC_MAC_SRC,
 	ACTION_SET_MAC_DST,
 	ACTION_SET_MAC_DST_MAC_DST,
+	ACTION_SET_METADATA,
+	ACTION_SET_METADATA_ID,
+	ACTION_SET_METADATA_DATA,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -610,6 +616,7 @@ struct parse_action_priv {
 	ITEM_ICMP6_ND_OPT_SLA_ETH,
 	ITEM_ICMP6_ND_OPT_TLA_ETH,
 	ITEM_META,
+	ITEM_METADATA,
 	ZERO,
 };
 
@@ -836,6 +843,13 @@ struct parse_action_priv {
 	ZERO,
 };
 
+static const enum index item_metadata[] = {
+	ITEM_METADATA_ID,
+	ITEM_METADATA_DATA,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -885,6 +899,7 @@ struct parse_action_priv {
 	ACTION_SET_TTL,
 	ACTION_SET_MAC_SRC,
 	ACTION_SET_MAC_DST,
+	ACTION_SET_METADATA,
 	ZERO,
 };
 
@@ -1047,6 +1062,14 @@ struct parse_action_priv {
 	ZERO,
 };
 
+static const enum index action_set_metadata[] = {
+	ACTION_SET_METADATA,
+	ACTION_SET_METADATA_ID,
+	ACTION_SET_METADATA_DATA,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -2147,6 +2170,27 @@ static int comp_vc_action_rss_queue(struct context *, const struct token *,
 		.name = "data",
 		.help = "metadata value",
 		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
+					     data, "\xff\xff\xff\xff")),
+	},
+	[ITEM_METADATA] = {
+		.name = "metadata",
+		.help = "match on metadata info",
+		.priv = PRIV_ITEM(METADATA,
+				  sizeof(struct rte_flow_item_metadata)),
+		.next = NEXT(item_metadata),
+		.call = parse_vc,
+	},
+	[ITEM_METADATA_ID] = {
+		.name = "id",
+		.help = " device-specific location of metadata",
+		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_metadata, id)),
+	},
+	[ITEM_METADATA_DATA] = {
+		.name = "data",
+		.help = "metadata data value",
+		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
 						  data, "\xff\xff\xff\xff")),
 	},
@@ -2854,6 +2898,30 @@ static int comp_vc_action_rss_queue(struct context *, const struct token *,
 			     (struct rte_flow_action_set_mac, mac_addr)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_SET_METADATA] = {
+		.name = "set_meta_data",
+		.help = "attach metadata info to flow packets",
+		.priv = PRIV_ACTION(SET_METADATA,
+			sizeof(struct rte_flow_action_set_metadata)),
+		.next = NEXT(action_set_metadata),
+		.call = parse_vc,
+	},
+	[ACTION_SET_METADATA_ID] = {
+		.name = "id",
+		.help = "device-specific metadata id to use",
+		.next = NEXT(action_set_metadata, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_metadata,
+					id)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_SET_METADATA_DATA] = {
+		.name = "data",
+		.help = "data to use",
+		.next = NEXT(action_set_metadata, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_metadata,
+					data)),
+		.call = parse_vc_conf,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 937f52b..743c357 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1210,6 +1210,30 @@ Matches an application specific 32 bit metadata item.
    | ``mask`` | ``data`` | bit-mask applies to "spec" and "last" |
    +----------+----------+---------------------------------------+
 
+Item: ``METADATA``
+^^^^^^^^^^^^^^^^^^
+
+Matches an application specific 32 bit metadata item present in the specified
+location of a device-specific, per-packet metadata information.
+This information is set either by a ``METADATA`` action in a previously matched
+rule or by the device hardware itself.
+
+This item may be specified several times as a match criteria on several metadata
+fields.
+
+Note the value of the data field is arbitrary and is PMD or application defined.
+The value of the id field is device-dependent.
+
+Depending on the underlying implementation the METADATA item may be supported
+as a set of registers or a memory region on the physical device,
+with virtual groups in the PMD or not supported at all.
+
+- ``id``: The metadata field id to match.
+- ``data``: The data to match against.
+
+- Default ``mask`` matches the specified integer value in the specified
+  metadata location.
+
 Actions
 ~~~~~~~
 
@@ -1476,6 +1500,32 @@ sets the ``PKT_RX_FDIR`` mbuf flag.
    | no properties |
    +---------------+
 
+Action: ``METADATA``
+^^^^^^^^^^^^^^^^^^^^
+
+Insetrs a 32 bit integer value in the specified location of a device-specific
+metadata information attached to each packet of a flow.
+
+This value is arbitrary and is application or PMD defined.
+Maximum allowed value depends on the underlying implementation.
+
+Depending on the underlying implementation the METADATA action may be supported
+as a set of registers or a memory region on the physical device, with virtual
+groups in the PMD or not supported at all.
+
+.. _table_rte_flow_action_metadata:
+
+.. table:: METADATA
+
+   +----------+-----------------------------------------------------------+
+   | Field    | Value                                                     |
+   +==========+===========================================================+
+   | ``id``   | unsigned integer value indicating where to write the data |
+   |          | in the metadata info.                                     |
+   +----------+-----------------------------------------------------------+
+   | ``data`` | unsigned integer value of data to write                   |
+   +----------+-----------------------------------------------------------+
+
 Action: ``QUEUE``
 ^^^^^^^^^^^^^^^^^
 
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 3277be1..ea2b9a0 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -74,6 +74,7 @@ struct rte_flow_desc_data {
 		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 	MK_FLOW_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
 	MK_FLOW_ITEM(META, sizeof(struct rte_flow_item_meta)),
+	MK_FLOW_ITEM(METADATA, sizeof(struct rte_flow_item_metadata)),
 };
 
 /** Generate flow_action[] entry. */
@@ -143,6 +144,8 @@ struct rte_flow_desc_data {
 	MK_FLOW_ACTION(SET_TTL, sizeof(struct rte_flow_action_set_ttl)),
 	MK_FLOW_ACTION(SET_MAC_SRC, sizeof(struct rte_flow_action_set_mac)),
 	MK_FLOW_ACTION(SET_MAC_DST, sizeof(struct rte_flow_action_set_mac)),
+	MK_FLOW_ACTION(SET_METADATA,
+		       sizeof(struct rte_flow_action_set_metadata)),
 };
 
 static int
diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 63f84fc..801831f 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -421,6 +421,15 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_meta.
 	 */
 	RTE_FLOW_ITEM_TYPE_META,
+
+	/**
+	 * [METADATA]
+	 *
+	 * Matches a metadata value specified in device-specific metadata field
+	 * attached to each flow.
+	 * See struct rte_flow_item_metadata.
+	 */
+	RTE_FLOW_ITEM_TYPE_METADATA,
 };
 
 /**
@@ -1183,6 +1192,33 @@ struct rte_flow_item_meta {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
+ * RTE_FLOW_ITEM_TYPE_METADATA.
+ *
+ * Matches an arbitrary integer value in the device-specific per-flow metadata
+ * location identified by the given id.
+ * This data value may have been set using the `METADATA` action in a previously
+ * matched rule or by the underlying hardware itself.
+ *
+ * The offset field is device-specific and its interpretation may change
+ * according to the device in use and its current configuration.
+ */
+struct rte_flow_item_metadata {
+	uint32_t id;
+	rte_be32_t data;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_METADATA. */
+#ifndef __cplusplus
+static const struct rte_flow_item_metadata rte_flow_item_metadata_mask = {
+	.id = UINT32_MAX,
+	.data = RTE_BE32(UINT32_MAX),
+};
+#endif
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
  * RTE_FLOW_ITEM_TYPE_MARK
  *
  * Matches an arbitrary integer value which was set using the ``MARK`` action
@@ -1650,6 +1686,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_set_mac.
 	 */
 	RTE_FLOW_ACTION_TYPE_SET_MAC_DST,
+
+	/**
+	 * Attaches an integer value to device-specific metadata info attached
+	 * to each packet in a flow.
+	 *
+	 * See struct rte_flow_action_set_metadata.
+	 */
+	RTE_FLOW_ACTION_TYPE_SET_METADATA,
 };
 
 /**
@@ -2131,6 +2175,23 @@ struct rte_flow_action_set_mac {
 	uint8_t mac_addr[ETHER_ADDR_LEN];
 };
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_SET_METADATA.
+ *
+ * Attaches an integer value to device-specific metadata info attached
+ * to each packet in a flow.
+ *
+ * The offset field is device-specific and its interpretation may change
+ * according to the device in use and its current configuration.
+ */
+struct rte_flow_action_set_metadata {
+	uint32_t id;
+	rte_be32_t data;
+};
+
 /*
  * Definition of a single action.
  *
