diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index a1e20a6..f4f654f 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -64,6 +64,7 @@ New Features
 
   New APIs are introduced to support binding / unbinding 2 ports hairpin.
   Hairpin TX part flow rules can be inserted explicitly.
+  New API is added to get the hairpin peer ports list.
 
 * **Updated Broadcom bnxt driver.**
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 14b9f3a..1cdfe4d 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -2208,6 +2208,30 @@ struct rte_eth_dev *
 	return ret;
 }
 
+int
+rte_eth_hairpin_get_peer_ports(uint16_t cur_port, uint16_t *peer_ports,
+			       size_t len, uint32_t direction)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	if (!peer_ports || !len)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(cur_port, -EINVAL);
+	dev = &rte_eth_devices[cur_port];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->hairpin_get_peer_ports,
+				-ENOTSUP);
+
+	ret = (*dev->dev_ops->hairpin_get_peer_ports)(dev, peer_ports,
+						      len, direction);
+	if (ret < 0)
+		RTE_ETHDEV_LOG(ERR, "Failed to get %d hairpin peer %s ports",
+			       cur_port, direction ? "RX" : "TX");
+
+	return ret;
+}
+
 void
 rte_eth_tx_buffer_drop_callback(struct rte_mbuf **pkts, uint16_t unsent,
 		void *userdata __rte_unused)
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 938df08..13f6fc0 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -2186,6 +2186,35 @@ int rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id,
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
  *
+ * Get all the hairpin peer RX / TX ports of the current port.
+ * The caller should ensure that the array is large enough to save the ports
+ * list.
+ *
+ * @param cur_port
+ *   The current port identifier of the Ethernet device.
+ * @param peer_ports
+ *   Pointer to the array to store the peer ports list.
+ * @param len
+ *   Length of the array to store the port identifiers.
+ * @param direction
+ *   Current port to peer port direction
+ *   positive - current used as TX to get all peer RX ports.
+ *   zero - current used as RX to get all peer TX ports.
+ *
+ * @return
+ *   - (0 or positive) actual peer ports number.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - Others detailed errors from PMD drivers.
+ */
+__rte_experimental
+int rte_eth_hairpin_get_peer_ports(uint16_t cur_port, uint16_t *peer_ports,
+				   size_t len, uint32_t direction);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
  * Bind all hairpin TX queues of one port to the RX queues of the peer port.
  * It is only allowed to call this API after all hairpin queues are configured
  * properly and the devices of TX and peer RX are in started state.
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 26ded15..3c3c859 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -657,6 +657,37 @@ typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
 
 /**
  * @internal
+ * Get all hairpin TX/RX peer ports of the current device, if any.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param peer_ports
+ *   array to save the ports list.
+ * @param len
+ *   array length.
+ * @param direction
+ *   value to decide the current to peer direction
+ *   positive - used as TX to get all peer RX ports.
+ *   zero - used as RX to get all peer TX ports.
+ *
+ * @return
+ *   Negative errno value on error, 0 or positive on success.
+ *
+ * @retval 0
+ *   Success, no peer ports.
+ * @retval >0
+ *   Actual number of the peer ports.
+ * @retval -ENOTSUP
+ *   Get peer ports API is not supported.
+ * @retval -EINVAL
+ *   One of the parameters is invalid.
+ */
+typedef int (*hairpin_get_peer_ports_t)(struct rte_eth_dev *dev,
+					uint16_t *peer_ports, size_t len,
+					uint32_t direction);
+
+/**
+ * @internal
  * Bind all hairpin TX queues of one port to the RX queues of the peer port.
  *
  * @param dev
@@ -849,6 +880,8 @@ struct eth_dev_ops {
 	/**< Get Forward Error Correction(FEC) mode. */
 	eth_fec_set_t fec_set;
 	/**< Set Forward Error Correction(FEC) mode. */
+	hairpin_get_peer_ports_t hairpin_get_peer_ports;
+	/**< Get hairpin peer ports list. */
 	eth_hairpin_bind_t hairpin_bind;
 	/**< Bind all hairpin TX queues of device to the peer port RX queues. */
 	eth_hairpin_unbind_t hairpin_unbind;
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 1aee03a..e644391 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -228,6 +228,7 @@ EXPERIMENTAL {
 
 	# added in 20.11
 	rte_eth_hairpin_bind;
+	rte_eth_hairpin_get_peer_ports;
 	rte_eth_hairpin_unbind;
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
