rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n");
 
        for (port_id = 0; port_id < nr_ports; port_id++) {
+               uint64_t rx_metadata = 0;
+
+               rx_metadata |= RTE_ETH_RX_METADATA_USER_FLAG;
+               rx_metadata |= RTE_ETH_RX_METADATA_USER_MARK;
+
+               ret = rte_eth_rx_metadata_negotiate(port_id, &rx_metadata);
+               if (ret == 0) {
+                       if (!(rx_metadata & RTE_ETH_RX_METADATA_USER_FLAG)) {
+                               printf(":: flow action FLAG will not affect Rx mbufs on port=%u\n",
+                                      port_id);
+                       }
+
+                       if (!(rx_metadata & RTE_ETH_RX_METADATA_USER_MARK)) {
+                               printf(":: flow action MARK will not affect Rx mbufs on port=%u\n",
+                                      port_id);
+                       }
+               } else if (ret != -ENOTSUP) {
+                       rte_exit(EXIT_FAILURE, "Error when negotiating Rx meta features on port=%u: %s\n",
+                                port_id, rte_strerror(-ret));
+               }
+
                ret = rte_eth_dev_info_get(port_id, &dev_info);
                if (ret != 0)
                        rte_exit(EXIT_FAILURE,
 
  */
 unsigned int num_procs = 1;
 
+static void
+eth_rx_metadata_negotiate_mp(uint16_t port_id)
+{
+       uint64_t rx_meta_features = 0;
+       int ret;
+
+       if (!is_proc_primary())
+               return;
+
+       rx_meta_features |= RTE_ETH_RX_METADATA_USER_FLAG;
+       rx_meta_features |= RTE_ETH_RX_METADATA_USER_MARK;
+       rx_meta_features |= RTE_ETH_RX_METADATA_TUNNEL_ID;
+
+       ret = rte_eth_rx_metadata_negotiate(port_id, &rx_meta_features);
+       if (ret == 0) {
+               if (!(rx_meta_features & RTE_ETH_RX_METADATA_USER_FLAG)) {
+                       TESTPMD_LOG(DEBUG, "Flow action FLAG will not affect Rx mbufs on port %u\n",
+                                   port_id);
+               }
+
+               if (!(rx_meta_features & RTE_ETH_RX_METADATA_USER_MARK)) {
+                       TESTPMD_LOG(DEBUG, "Flow action MARK will not affect Rx mbufs on port %u\n",
+                                   port_id);
+               }
+
+               if (!(rx_meta_features & RTE_ETH_RX_METADATA_TUNNEL_ID)) {
+                       TESTPMD_LOG(DEBUG, "Flow tunnel offload support might be limited or unavailable on port %u\n",
+                                   port_id);
+               }
+       } else if (ret != -ENOTSUP) {
+               rte_exit(EXIT_FAILURE, "Error when negotiating Rx meta features on port %u: %s\n",
+                        port_id, rte_strerror(-ret));
+       }
+}
+
 static int
 eth_dev_configure_mp(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                      const struct rte_eth_conf *dev_conf)
        int ret;
        int i;
 
+       eth_rx_metadata_negotiate_mp(pid);
+
        port->dev_conf.txmode = tx_mode;
        port->dev_conf.rxmode = rx_mode;
 
 
   Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and
   TCP/UDP/SCTP header checksum field can be used as input set for RSS.
 
+* **Added ethdev support to control delivery of Rx metadata from the HW to the PMD.**
+
+  A new API, ``rte_eth_rx_metadata_negotiate()``, was added.
+  The following parts of Rx metadata were defined:
+
+  * ``RTE_ETH_RX_METADATA_USER_FLAG``
+  * ``RTE_ETH_RX_METADATA_USER_MARK``
+  * ``RTE_ETH_RX_METADATA_TUNNEL_ID``
+
 * **Updated af_packet ethdev driver.**
 
   * Default VLAN strip behavior was changed. VLAN tag won't be stripped
 
 typedef int (*eth_representor_info_get_t)(struct rte_eth_dev *dev,
        struct rte_eth_representor_info *info);
 
+/**
+ * @internal
+ * Negotiate the NIC's ability to deliver specific kinds of metadata to the PMD.
+ *
+ * @param dev
+ *   Port (ethdev) handle
+ *
+ * @param[inout] features
+ *   Feature selection buffer
+ *
+ * @return
+ *   Negative errno value on error, zero otherwise
+ */
+typedef int (*eth_rx_metadata_negotiate_t)(struct rte_eth_dev *dev,
+                                      uint64_t *features);
+
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 
        eth_representor_info_get_t representor_info_get;
        /**< Get representor info. */
+
+       /**
+        * Negotiate the NIC's ability to deliver specific
+        * kinds of metadata to the PMD.
+        */
+       eth_rx_metadata_negotiate_t rx_metadata_negotiate;
 };
 
 /**
 
        return eth_err(port_id, (*dev->dev_ops->representor_info_get)(dev, info));
 }
 
+int
+rte_eth_rx_metadata_negotiate(uint16_t port_id, uint64_t *features)
+{
+       struct rte_eth_dev *dev;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       dev = &rte_eth_devices[port_id];
+
+       if (dev->data->dev_configured != 0) {
+               RTE_ETHDEV_LOG(ERR,
+                       "The port (id=%"PRIu16") is already configured\n",
+                       port_id);
+               return -EBUSY;
+       }
+
+       if (features == NULL) {
+               RTE_ETHDEV_LOG(ERR, "Invalid features (NULL)\n");
+               return -EINVAL;
+       }
+
+       RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_metadata_negotiate, -ENOTSUP);
+       return eth_err(port_id,
+                      (*dev->dev_ops->rx_metadata_negotiate)(dev, features));
+}
+
 RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
 
 RTE_INIT(ethdev_init_telemetry)
 
 int rte_eth_representor_info_get(uint16_t port_id,
                                 struct rte_eth_representor_info *info);
 
+/** The NIC is able to deliver flag (if set) with packets to the PMD. */
+#define RTE_ETH_RX_METADATA_USER_FLAG (UINT64_C(1) << 0)
+
+/** The NIC is able to deliver mark ID with packets to the PMD. */
+#define RTE_ETH_RX_METADATA_USER_MARK (UINT64_C(1) << 1)
+
+/** The NIC is able to deliver tunnel ID with packets to the PMD. */
+#define RTE_ETH_RX_METADATA_TUNNEL_ID (UINT64_C(1) << 2)
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Negotiate the NIC's ability to deliver specific kinds of metadata to the PMD.
+ *
+ * Invoke this API before the first rte_eth_dev_configure() invocation
+ * to let the PMD make preparations that are inconvenient to do later.
+ *
+ * The negotiation process is as follows:
+ *
+ * - the application requests features intending to use at least some of them;
+ * - the PMD responds with the guaranteed subset of the requested feature set;
+ * - the application can retry negotiation with another set of features;
+ * - the application can pass zero to clear the negotiation result;
+ * - the last negotiated result takes effect upon
+ *   the ethdev configure and start.
+ *
+ * @note
+ *   The PMD is supposed to first consider enabling the requested feature set
+ *   in its entirety. Only if it fails to do so, does it have the right to
+ *   respond with a smaller set of the originally requested features.
+ *
+ * @note
+ *   Return code (-ENOTSUP) does not necessarily mean that the requested
+ *   features are unsupported. In this case, the application should just
+ *   assume that these features can be used without prior negotiations.
+ *
+ * @param port_id
+ *   Port (ethdev) identifier
+ *
+ * @param[inout] features
+ *   Feature selection buffer
+ *
+ * @return
+ *   - (-EBUSY) if the port can't handle this in its current state;
+ *   - (-ENOTSUP) if the method itself is not supported by the PMD;
+ *   - (-ENODEV) if *port_id* is invalid;
+ *   - (-EINVAL) if *features* is NULL;
+ *   - (-EIO) if the device is removed;
+ *   - (0) on success
+ */
+__rte_experimental
+int rte_eth_rx_metadata_negotiate(uint16_t port_id, uint64_t *features);
+
 #include <rte_ethdev_core.h>
 
 /**
 
         * PKT_RX_FDIR_ID mbuf flags.
         *
         * See struct rte_flow_action_mark.
+        *
+        * One should negotiate mark delivery from the NIC to the PMD.
+        * @see rte_eth_rx_metadata_negotiate()
+        * @see RTE_ETH_RX_METADATA_USER_MARK
         */
        RTE_FLOW_ACTION_TYPE_MARK,
 
         * sets the PKT_RX_FDIR mbuf flag.
         *
         * No associated configuration structure.
+        *
+        * One should negotiate flag delivery from the NIC to the PMD.
+        * @see rte_eth_rx_metadata_negotiate()
+        * @see RTE_ETH_RX_METADATA_USER_FLAG
         */
        RTE_FLOW_ACTION_TYPE_FLAG,
 
 /**
  * Populate the current packet processing state, if exists, for the given mbuf.
  *
+ * One should negotiate tunnel metadata delivery from the NIC to the HW.
+ * @see rte_eth_rx_metadata_negotiate()
+ * @see RTE_ETH_RX_METADATA_TUNNEL_ID
+ *
  * @param port_id
  *   Port identifier of Ethernet device.
  * @param[in] m
 
        rte_mtr_meter_policy_delete;
        rte_mtr_meter_policy_update;
        rte_mtr_meter_policy_validate;
+
+       # added in 21.11
+       rte_eth_rx_metadata_negotiate;
 };
 
 INTERNAL {