[v6] ethdev: introduce available Rx descriptors threshold

Message ID 20220608163528.1850326-1-andrew.rybchenko@oktetlabs.ru (mailing list archive)
State Accepted, archived
Delegated to: Andrew Rybchenko
Headers
Series [v6] ethdev: introduce available Rx descriptors threshold |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-abi-testing warning Testing issues

Commit Message

Andrew Rybchenko June 8, 2022, 4:35 p.m. UTC
  From: Spike Du <spiked@nvidia.com>

A new event RTE_ETH_EVENT_RX_AVAIL_THRESH should be generated by HW
when number of available descriptors in Rx queue goes below the
threshold.

The threshold is defined as a percentage of an Rx queue size with valid
values from 0 to 99 (inclusive). Zero (default) value disables it.

There is no capability reporting for the feature. Application should
simply try to set required threshold value and handle result.

Add testpmd commands to control the threshold:
  set port <port_id> rxq <rxq_id> avail_thresh <avail_thresh_num>

Signed-off-by: Spike Du <spiked@nvidia.com>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
v6:
    - try to make descriptor shorter and more useful
    - refine terminology to use "available descriptors threshold"
      everywhere (plural "descriptors")
    - fix ethdev API documenation
    - define negative return values
    - define rules to convert percentage to descriptors number
      in drivers
    - avoid extra checks in testpmd helper to allow ethdev API
      to do its job
    - minor fixes in testpmd variables naming
    - fix testpmd help to be human oriented
    - update testpmd users guide
    - add release notes

 app/test-pmd/cmdline.c                      | 72 +++++++++++++++++++++
 app/test-pmd/config.c                       |  9 +++
 app/test-pmd/testpmd.c                      | 16 +++++
 app/test-pmd/testpmd.h                      |  2 +
 doc/guides/rel_notes/release_22_07.rst      |  6 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  9 +++
 lib/ethdev/ethdev_driver.h                  | 25 +++++++
 lib/ethdev/rte_ethdev.c                     | 44 +++++++++++++
 lib/ethdev/rte_ethdev.h                     | 71 ++++++++++++++++++++
 lib/ethdev/version.map                      |  2 +
 10 files changed, 256 insertions(+)
  

Comments

Thomas Monjalon June 8, 2022, 5:22 p.m. UTC | #1
08/06/2022 18:35, Andrew Rybchenko:
> From: Spike Du <spiked@nvidia.com>
> 
> A new event RTE_ETH_EVENT_RX_AVAIL_THRESH should be generated by HW
> when number of available descriptors in Rx queue goes below the
> threshold.
> 
> The threshold is defined as a percentage of an Rx queue size with valid
> values from 0 to 99 (inclusive). Zero (default) value disables it.
> 
> There is no capability reporting for the feature. Application should
> simply try to set required threshold value and handle result.
> 
> Add testpmd commands to control the threshold:
>   set port <port_id> rxq <rxq_id> avail_thresh <avail_thresh_num>
> 
> Signed-off-by: Spike Du <spiked@nvidia.com>
> Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> ---
> v6:
>     - try to make descriptor shorter and more useful
>     - refine terminology to use "available descriptors threshold"
>       everywhere (plural "descriptors")
>     - fix ethdev API documenation
>     - define negative return values
>     - define rules to convert percentage to descriptors number
>       in drivers
>     - avoid extra checks in testpmd helper to allow ethdev API
>       to do its job
>     - minor fixes in testpmd variables naming
>     - fix testpmd help to be human oriented
>     - update testpmd users guide
>     - add release notes

What a (more than) review work, thanks a lot for this v6!

Acked-by: Thomas Monjalon <thomas@monjalon.net>

With a few minor arrangements,
applied, thanks.
  
Thomas Monjalon June 8, 2022, 5:46 p.m. UTC | #2
08/06/2022 19:22, Thomas Monjalon:
> 08/06/2022 18:35, Andrew Rybchenko:
> > From: Spike Du <spiked@nvidia.com>
> > 
> > A new event RTE_ETH_EVENT_RX_AVAIL_THRESH should be generated by HW
> > when number of available descriptors in Rx queue goes below the
> > threshold.
> > 
> > The threshold is defined as a percentage of an Rx queue size with valid
> > values from 0 to 99 (inclusive). Zero (default) value disables it.
> > 
> > There is no capability reporting for the feature. Application should
> > simply try to set required threshold value and handle result.
> > 
> > Add testpmd commands to control the threshold:
> >   set port <port_id> rxq <rxq_id> avail_thresh <avail_thresh_num>
> > 
> > Signed-off-by: Spike Du <spiked@nvidia.com>
> > Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> > ---
> > v6:
> >     - try to make descriptor shorter and more useful
> >     - refine terminology to use "available descriptors threshold"
> >       everywhere (plural "descriptors")
> >     - fix ethdev API documenation
> >     - define negative return values
> >     - define rules to convert percentage to descriptors number
> >       in drivers
> >     - avoid extra checks in testpmd helper to allow ethdev API
> >       to do its job
> >     - minor fixes in testpmd variables naming
> >     - fix testpmd help to be human oriented
> >     - update testpmd users guide
> >     - add release notes
> 
> What a (more than) review work, thanks a lot for this v6!
> 
> Acked-by: Thomas Monjalon <thomas@monjalon.net>
> 
> With a few minor arrangements,
> applied, thanks.

PS: some ABI exceptions have to be added as discussed in the thread:

+; Ignore ethdev event enum update
+; because new event cannot be received if not registered
+[suppress_type]
+        type_kind = enum
+        changed_enumerators = RTE_ETH_EVENT_MAX
+
+; Ignore fields inserted in cacheline boundary of rte_eth_rxq_info
+; because the struct size is unchanged
+[suppress_type]
+        name = rte_eth_rxq_info
+        has_data_member_inserted_between = {offset_of(rx_buf_size), end}
  
fengchengwen June 9, 2022, 12:17 a.m. UTC | #3
Hi Thomas,

   Could it possible accept the patch ' [dpdk-dev] [PATCH v7 1/4] ethdev: support device reset and recovery events'
which was delayed by ABI exceptions like this patch ?

   PS: I noticed RC-1 was released just now and there may be no window left, but I think since this patch can be an
exception, why not that patch ?

Thanks.

On 2022/6/9 1:46, Thomas Monjalon wrote:
> 08/06/2022 19:22, Thomas Monjalon:
>> 08/06/2022 18:35, Andrew Rybchenko:
>>> From: Spike Du <spiked@nvidia.com>
>>>
>>> A new event RTE_ETH_EVENT_RX_AVAIL_THRESH should be generated by HW
>>> when number of available descriptors in Rx queue goes below the
>>> threshold.
>>>
>>> The threshold is defined as a percentage of an Rx queue size with valid
>>> values from 0 to 99 (inclusive). Zero (default) value disables it.
>>>
>>> There is no capability reporting for the feature. Application should
>>> simply try to set required threshold value and handle result.
>>>
>>> Add testpmd commands to control the threshold:
>>>   set port <port_id> rxq <rxq_id> avail_thresh <avail_thresh_num>
>>>
>>> Signed-off-by: Spike Du <spiked@nvidia.com>
>>> Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>>> ---
>>> v6:
>>>     - try to make descriptor shorter and more useful
>>>     - refine terminology to use "available descriptors threshold"
>>>       everywhere (plural "descriptors")
>>>     - fix ethdev API documenation
>>>     - define negative return values
>>>     - define rules to convert percentage to descriptors number
>>>       in drivers
>>>     - avoid extra checks in testpmd helper to allow ethdev API
>>>       to do its job
>>>     - minor fixes in testpmd variables naming
>>>     - fix testpmd help to be human oriented
>>>     - update testpmd users guide
>>>     - add release notes
>>
>> What a (more than) review work, thanks a lot for this v6!
>>
>> Acked-by: Thomas Monjalon <thomas@monjalon.net>
>>
>> With a few minor arrangements,
>> applied, thanks.
> 
> PS: some ABI exceptions have to be added as discussed in the thread:
> 
> +; Ignore ethdev event enum update
> +; because new event cannot be received if not registered
> +[suppress_type]
> +        type_kind = enum
> +        changed_enumerators = RTE_ETH_EVENT_MAX
> +
> +; Ignore fields inserted in cacheline boundary of rte_eth_rxq_info
> +; because the struct size is unchanged
> +[suppress_type]
> +        name = rte_eth_rxq_info
> +        has_data_member_inserted_between = {offset_of(rx_buf_size), end}
> 
> 
> 
> 
> 
> .
>
  
Thomas Monjalon June 9, 2022, 7:05 a.m. UTC | #4
09/06/2022 02:17, fengchengwen:
> Hi Thomas,
> 
>    Could it possible accept the patch ' [dpdk-dev] [PATCH v7 1/4] ethdev: support device reset and recovery events'
> which was delayed by ABI exceptions like this patch ?

I suppose you refer to this explanation:

+; Ignore ethdev event enum update
+; because new event cannot be received if not registered

That's true we discussed in the past that it should have no effect
on applications compiled with an old version of DPDK.

>    PS: I noticed RC-1 was released just now and there may be no window left, but I think since this patch can be an
> exception, why not that patch ?

As far as I remember, the reset and recovery events patch
have other comments to address before it can be accepted.
  
fengchengwen June 10, 2022, 12:01 a.m. UTC | #5
Hi Thomas,

On 2022/6/9 15:05, Thomas Monjalon wrote:
> 09/06/2022 02:17, fengchengwen:
>> Hi Thomas,
>>
>>    Could it possible accept the patch ' [dpdk-dev] [PATCH v7 1/4] ethdev: support device reset and recovery events'
>> which was delayed by ABI exceptions like this patch ?
> 
> I suppose you refer to this explanation:

Yes

> 
> +; Ignore ethdev event enum update
> +; because new event cannot be received if not registered
> 
> That's true we discussed in the past that it should have no effect
> on applications compiled with an old version of DPDK.
> 
>>    PS: I noticed RC-1 was released just now and there may be no window left, but I think since this patch can be an
>> exception, why not that patch ?
> 
> As far as I remember, the reset and recovery events patch
> have other comments to address before it can be accepted.

Yes, but the ABI exceptions is the primary cause of blockage.

There's two weeks left to fully discuss I think.

We have product requirements for this feature ("device reset and recovery events"), So:

Hi kalesh-anakkur,

  Could you please send a new version about it ?  If not, do you mind if I re-develop over it ?

> 
> 
> 
> .
>
  

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index fdd0cada3b..3acdd33cd9 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -750,6 +750,9 @@  static void cmd_help_long_parsed(void *parsed_result,
 			"set port (port_id) fec_mode auto|off|rs|baser\n"
 			"    set fec mode for a specific port\n\n"
 
+			"set port (port_id) rxq (queue_id) avail_thresh (0..99)>\n "
+			"    set available descriptors threshold for Rx queue\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -17331,6 +17334,74 @@  static cmdline_parse_inst_t cmd_set_fec_mode = {
 	},
 };
 
+/* *** set available descriptors threshold for an RxQ of a port *** */
+struct cmd_set_rxq_avail_thresh_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint16_t port_num;
+	cmdline_fixed_string_t rxq;
+	uint16_t rxq_num;
+	cmdline_fixed_string_t avail_thresh;
+	uint8_t avail_thresh_num;
+};
+
+static void cmd_set_rxq_avail_thresh_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_set_rxq_avail_thresh_result *res = parsed_result;
+	int ret = 0;
+
+	if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0)
+	    && (strcmp(res->rxq, "rxq") == 0)
+	    && (strcmp(res->avail_thresh, "avail_thresh") == 0))
+		ret = set_rxq_avail_thresh(res->port_num, res->rxq_num,
+				  res->avail_thresh_num);
+	if (ret < 0)
+		printf("rxq_avail_thresh_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+static cmdline_parse_token_string_t cmd_set_rxq_avail_thresh_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				set, "set");
+static cmdline_parse_token_string_t cmd_set_rxq_avail_thresh_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				port, "port");
+static cmdline_parse_token_num_t cmd_set_rxq_avail_thresh_portnum =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				port_num, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_set_rxq_avail_thresh_rxq =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				rxq, "rxq");
+static cmdline_parse_token_num_t cmd_set_rxq_avail_thresh_rxqnum =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				rxq_num, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_set_rxq_avail_thresh_avail_thresh =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				avail_thresh, "avail_thresh");
+static cmdline_parse_token_num_t cmd_set_rxq_avail_thresh_avail_threshnum =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_rxq_avail_thresh_result,
+				avail_thresh_num, RTE_UINT8);
+
+static cmdline_parse_inst_t cmd_set_rxq_avail_thresh = {
+	.f = cmd_set_rxq_avail_thresh_parsed,
+	.data = (void *)0,
+	.help_str =
+		"set port <port_id> rxq <queue_id> avail_thresh <0..99>: "
+		"Set available descriptors threshold for Rx queue",
+	.tokens = {
+		(void *)&cmd_set_rxq_avail_thresh_set,
+		(void *)&cmd_set_rxq_avail_thresh_port,
+		(void *)&cmd_set_rxq_avail_thresh_portnum,
+		(void *)&cmd_set_rxq_avail_thresh_rxq,
+		(void *)&cmd_set_rxq_avail_thresh_rxqnum,
+		(void *)&cmd_set_rxq_avail_thresh_avail_thresh,
+		(void *)&cmd_set_rxq_avail_thresh_avail_threshnum,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -18110,6 +18181,7 @@  static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
 	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
 	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_rxq_avail_thresh,
 	(cmdline_parse_inst_t *)&cmd_show_capability,
 	(cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
 	(cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index d6caa1f0b2..e490d7f921 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -6392,3 +6392,12 @@  show_mcast_macs(portid_t port_id)
 		printf("  %s\n", buf);
 	}
 }
+
+int
+set_rxq_avail_thresh(portid_t port_id, uint16_t queue_id, uint8_t avail_thresh)
+{
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return -EINVAL;
+
+	return rte_eth_rx_avail_thresh_set(port_id, queue_id, avail_thresh);
+}
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 9d6175e9a7..3e39584549 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -420,6 +420,7 @@  static const char * const eth_event_desc[] = {
 	[RTE_ETH_EVENT_NEW] = "device probed",
 	[RTE_ETH_EVENT_DESTROY] = "device released",
 	[RTE_ETH_EVENT_FLOW_AGED] = "flow aged",
+	[RTE_ETH_EVENT_RX_AVAIL_THRESH] = "RxQ available descriptors threshold reached",
 	[RTE_ETH_EVENT_MAX] = NULL,
 };
 
@@ -3672,6 +3673,21 @@  eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
 		ports[port_id].port_status = RTE_PORT_CLOSED;
 		printf("Port %u is closed\n", port_id);
 		break;
+	case RTE_ETH_EVENT_RX_AVAIL_THRESH: {
+		uint16_t rxq_id;
+		int ret;
+
+		/* avail_thresh query API rewinds rxq_id, no need to check max RxQ num */
+		for (rxq_id = 0; ; rxq_id++) {
+			ret = rte_eth_rx_avail_thresh_query(port_id, &rxq_id,
+							    NULL);
+			if (ret <= 0)
+				break;
+			printf("Received avail_thresh event, port:%u rxq_id:%u\n",
+			       port_id, rxq_id);
+		}
+		break;
+	}
 	default:
 		break;
 	}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index dd34b025e6..212d836a19 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1190,6 +1190,8 @@  int update_jumbo_frame_offload(portid_t portid);
 void flex_item_create(portid_t port_id, uint16_t flex_id, const char *filename);
 void flex_item_destroy(portid_t port_id, uint16_t flex_id);
 void port_flex_item_flush(portid_t port_id);
+int set_rxq_avail_thresh(portid_t port_id, uint16_t queue_id,
+			 uint8_t avail_thresh);
 
 extern int flow_parse(const char *src, void *result, unsigned int size,
 		      struct rte_flow_attr **attr,
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 5551332bcb..913add127c 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -73,6 +73,12 @@  New Features
     * SFF-8472 revision 12.0
     * SFF-8636 revision 2.7
 
+* **Added Rx queue available descriptors threshold and event.**
+
+  Added ethdev API and corresponding driver operations to set Rx queue
+  available descriptors threshold and query for queues with reached
+  threshold when a new event RTE_ETH_EVENT_RX_AVAIL_THRESH is received.
+
 * **Added vhost API to get the number of in-flight packets.**
 
   Added an API which can get the number of in-flight packets in
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index bbeba554eb..fb7d2839fe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2021,6 +2021,15 @@  Set fec mode for a specific port::
 
   testpmd> set port (port_id) fec_mode auto|off|rs|baser
 
+Set Rx queue available descriptors threshold
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set available descriptors threshold for a specific Rx queue of port::
+
+  testpmd> set port (port_id) rxq (queue_id) avail_thresh (0..99)
+
+Use 0 value to disable the threshold and corresponding event.
+
 Config Sample actions list
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 69d9dc21d8..5101868ea7 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1073,6 +1073,26 @@  typedef int (*eth_ip_reassembly_conf_set_t)(struct rte_eth_dev *dev,
  */
 typedef int (*eth_dev_priv_dump_t)(struct rte_eth_dev *dev, FILE *file);
 
+/**
+ * @internal Set Rx queue available descriptors threshold.
+ * @see rte_eth_rx_avail_thresh_set()
+ *
+ * Driver should round down number of descriptors on conversion from
+ * percentage.
+ */
+typedef int (*eth_rx_queue_avail_thresh_set_t)(struct rte_eth_dev *dev,
+				      uint16_t rx_queue_id,
+				      uint8_t avail_thresh);
+
+/**
+ * @internal Query Rx queue available descriptors threshold event.
+ * @see rte_eth_rx_avail_thresh_query()
+ */
+
+typedef int (*eth_rx_queue_avail_thresh_query_t)(struct rte_eth_dev *dev,
+					uint16_t *rx_queue_id,
+					uint8_t *avail_thresh);
+
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
@@ -1283,6 +1303,11 @@  struct eth_dev_ops {
 
 	/** Dump private info from device */
 	eth_dev_priv_dump_t eth_dev_priv_dump;
+
+	/** Set Rx queue available descriptors threshold */
+	eth_rx_queue_avail_thresh_set_t rx_queue_avail_thresh_set;
+	/** Query Rx queue available descriptors threshold event */
+	eth_rx_queue_avail_thresh_query_t rx_queue_avail_thresh_query;
 };
 
 /**
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index b9c5dea09f..90e50eb02b 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -4432,6 +4432,50 @@  int rte_eth_set_queue_rate_limit(uint16_t port_id, uint16_t queue_idx,
 							queue_idx, tx_rate));
 }
 
+int rte_eth_rx_avail_thresh_set(uint16_t port_id, uint16_t queue_id,
+			       uint8_t avail_thresh)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (queue_id > dev->data->nb_rx_queues) {
+		RTE_ETHDEV_LOG(ERR,
+			"Set queue avail thresh: port %u: invalid queue ID=%u.\n",
+			port_id, queue_id);
+		return -EINVAL;
+	}
+
+	if (avail_thresh > 99) {
+		RTE_ETHDEV_LOG(ERR,
+			"Set queue avail thresh: port %u: threshold should be <= 99.\n",
+			port_id);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_avail_thresh_set, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->rx_queue_avail_thresh_set)(dev,
+							     queue_id, avail_thresh));
+}
+
+int rte_eth_rx_avail_thresh_query(uint16_t port_id, uint16_t *queue_id,
+				 uint8_t *avail_thresh)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (queue_id == NULL)
+		return -EINVAL;
+	if (*queue_id >= dev->data->nb_rx_queues)
+		*queue_id = 0;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_avail_thresh_query, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->rx_queue_avail_thresh_query)(dev,
+							     queue_id, avail_thresh));
+}
+
 RTE_INIT(eth_dev_init_fp_ops)
 {
 	uint32_t i;
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 7baea176e8..1975224796 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -1931,6 +1931,13 @@  struct rte_eth_rxq_info {
 	uint8_t queue_state;        /**< one of RTE_ETH_QUEUE_STATE_*. */
 	uint16_t nb_desc;           /**< configured number of RXDs. */
 	uint16_t rx_buf_size;       /**< hardware receive buffer size. */
+	/**
+	 * Available Rx descriptors threshold defined as percentage
+	 * of Rx queue size. If number of available descriptors is lower,
+	 * the event RTE_ETH_EVENT_RX_AVAIL_THESH is generated.
+	 * Value 0 means that the threshold monitoring is disabled.
+	 */
+	uint8_t avail_thresh;
 } __rte_cache_min_aligned;
 
 /**
@@ -3652,6 +3659,65 @@  int rte_eth_dev_get_vlan_offload(uint16_t port_id);
  */
 int rte_eth_dev_set_vlan_pvid(uint16_t port_id, uint16_t pvid, int on);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Set Rx queue available descriptors threshold.
+ *
+ * @param port_id
+ *  The port identifier of the Ethernet device.
+ * @param queue_id
+ *  The index of the receive queue.
+ * @param avail_thresh
+ *  The available descriptors threshold is percentage of Rx queue size which
+ *  describes the availability of Rx queue for hardware. If the Rx queue
+ *  availability is below it, the device will generate the event
+ *  RTE_ETH_EVENT_RX_AVAIL_THRESH.
+ *  [1-99] to set a new available descriptors threshold.
+ *  0 to disable threshold monitoring.
+ *
+ * @return
+ *   - 0 if successful.
+ *   - (-ENODEV) if @p port_id is invalid.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if available Rx descriptors threshold is not supported.
+ *   - (-EIO) if device is removed.
+ */
+__rte_experimental
+int rte_eth_rx_avail_thresh_set(uint16_t port_id, uint16_t queue_id,
+			       uint8_t avail_thresh);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Find Rx queue with RTE_ETH_EVENT_RX_AVAIL_THRESH event pending.
+ *
+ * @param port_id
+ *  The port identifier of the Ethernet device.
+ * @param[inout] queue_id
+ *  On input starting Rx queue index to search from.
+ *  If the queue_id is bigger than maximum queue ID of the port,
+ *  search is started from 0. So that application can keep calling
+ *  this function to handle all pending events with a simple increment
+ *  of queue_id on the next call.
+ *  On output if return value is 1, Rx queue index with the event pending.
+ * @param[out] avail_thresh
+ *  Location for available descriptors threshold of the found Rx queue.
+ *
+ * @return
+ *   - 1 if an Rx queue with pending event is found.
+ *   - 0 if no Rx queue with pending event is found.
+ *   - (-ENODEV) if @p port_id is invalid.
+ *   - (-EINVAL) if bad parameter (e.g. @p queue_id is NULL).
+ *   - (-ENOTSUP) if operation is not supported.
+ *   - (-EIO) if device is removed.
+ */
+__rte_experimental
+int rte_eth_rx_avail_thresh_query(uint16_t port_id, uint16_t *queue_id,
+				 uint8_t *avail_thresh);
+
 typedef void (*buffer_tx_error_fn)(struct rte_mbuf **unsent, uint16_t count,
 		void *userdata);
 
@@ -3857,6 +3923,11 @@  enum rte_eth_event_type {
 	RTE_ETH_EVENT_DESTROY,  /**< port is released */
 	RTE_ETH_EVENT_IPSEC,    /**< IPsec offload related event */
 	RTE_ETH_EVENT_FLOW_AGED,/**< New aged-out flows is detected */
+	/**
+	 * Number of available Rx descriptors has become smaller than the threshold.
+	 * @see rte_eth_rx_avail_thresh_set()
+	 */
+	RTE_ETH_EVENT_RX_AVAIL_THRESH,
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 8a7ef35233..adfc9fe624 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -279,6 +279,8 @@  EXPERIMENTAL {
 	rte_flow_async_action_handle_update;
 
 	# added in 22.07
+	rte_eth_rx_avail_thresh_set;
+	rte_eth_rx_avail_thresh_query;
 	rte_mtr_color_in_protocol_get;
 	rte_mtr_color_in_protocol_priority_get;
 	rte_mtr_color_in_protocol_set;