[1/4] ethdev: introduce encap hash calculation

Message ID 20240128093943.4461-2-orika@nvidia.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series introduce encap hash calculation |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation warning apply patch failure
ci/iol-testing warning apply patch failure

Commit Message

Ori Kam Jan. 28, 2024, 9:39 a.m. UTC
During the encapsulation of a packet, it is expected to calculate the
hash value which is based on the original packet (the outer values,
which will become the inner values).

The tunnel protocol defines which tunnel field should hold this hash,
but it doesn't define the hash calculation algorithm.

An application that uses flow offloads gets the first few packets
and then decides to offload the flow. As a result, there are two
different paths that a packet from a given flow may take.
SW for the first few packets or HW for the rest.
When the packet goes through the SW, the SW encapsulates the packet
and must use the same hash calculation as the HW will do for
the rest of the packets in this flow.

This patch gives the SW a way to query the hash value
for a given packet as if the packet was passed through the HW.

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/prog_guide/rte_flow.rst     | 22 ++++++++++++
 doc/guides/rel_notes/release_24_03.rst |  4 +++
 lib/ethdev/rte_flow.c                  | 25 +++++++++++++
 lib/ethdev/rte_flow.h                  | 50 ++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  5 +++
 lib/ethdev/version.map                 |  1 +
 6 files changed, 107 insertions(+)
  

Comments

Ori Kam Feb. 1, 2024, 8:40 a.m. UTC | #1
Hi Ferruh,

Can you please review my patch?

Thanks,
Ori

> -----Original Message-----
> From: Ori Kam <orika@nvidia.com>
> Sent: Sunday, January 28, 2024 11:40 AM
> To: Dariusz Sosnowski <dsosnowski@nvidia.com>; ferruh.yigit@amd.com;
> 
> During the encapsulation of a packet, it is expected to calculate the
> hash value which is based on the original packet (the outer values,
> which will become the inner values).
> 
> The tunnel protocol defines which tunnel field should hold this hash,
> but it doesn't define the hash calculation algorithm.
> 
> An application that uses flow offloads gets the first few packets
> and then decides to offload the flow. As a result, there are two
> different paths that a packet from a given flow may take.
> SW for the first few packets or HW for the rest.
> When the packet goes through the SW, the SW encapsulates the packet
> and must use the same hash calculation as the HW will do for
> the rest of the packets in this flow.
> 
> This patch gives the SW a way to query the hash value
> for a given packet as if the packet was passed through the HW.
> 
> Signed-off-by: Ori Kam <orika@nvidia.com>
> ---
>  doc/guides/prog_guide/rte_flow.rst     | 22 ++++++++++++
>  doc/guides/rel_notes/release_24_03.rst |  4 +++
>  lib/ethdev/rte_flow.c                  | 25 +++++++++++++
>  lib/ethdev/rte_flow.h                  | 50 ++++++++++++++++++++++++++
>  lib/ethdev/rte_flow_driver.h           |  5 +++
>  lib/ethdev/version.map                 |  1 +
>  6 files changed, 107 insertions(+)
> 
> diff --git a/doc/guides/prog_guide/rte_flow.rst
> b/doc/guides/prog_guide/rte_flow.rst
> index 900fdaefb6..0435dda3c7 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -4211,6 +4211,28 @@ as it would be calculated in the HW.
>                              uint8_t pattern_template_index,
>  			                   uint32_t *hash, struct rte_flow_error
> *error);
> 
> +Calculate encap hash
> +~~~~~~~~~~~~~~~~~~~~
> +
> +Calculating hash of a packet in SW as it would be calculated in HW for the
> encap action
> +
> +When the HW execute an encapsulation action, it may calculate an hash
> value which is based
> +on the original packet. This hash is stored depending on the encapsulation
> protocol, in one
> +of the outer fields.
> +
> +This function allows the application to calculate the hash for a given packet
> as if the
> +encapsulation was done in HW.
> +
> +.. code-block:: c
> +
> +   int
> +   rte_flow_calc_encap_hash(uint16_t port_id,
> +                            const struct rte_flow_item pattern[],
> +			                   enum rte_flow_encap_hash_field
> dest_field,
> +                            uint8_t hash_len,
> +                            uint8_t *hash,
> +			                   struct rte_flow_error *error);
> +
>  .. _flow_isolated_mode:
> 
>  Flow isolated mode
> diff --git a/doc/guides/rel_notes/release_24_03.rst
> b/doc/guides/rel_notes/release_24_03.rst
> index 5e545da867..80af380172 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -75,6 +75,10 @@ New Features
>    * Added support for VXLAN-GPE matching in HW Steering flow engine
>      (``dv_flow_en`` = 2).
> 
> +* **Added ability to calculate the encap hash as done by HW.**
> +
> +  * Added function that calculates the encap hash, as the HW calculates it:
> +    ``rte_flow_calc_encap_hash()``
> 
>  Removed Items
>  -------------
> diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
> index 3f58d792f9..7fce754be1 100644
> --- a/lib/ethdev/rte_flow.c
> +++ b/lib/ethdev/rte_flow.c
> @@ -2482,3 +2482,28 @@ rte_flow_calc_table_hash(uint16_t port_id, const
> struct rte_flow_template_table
>  					hash, error);
>  	return flow_err(port_id, ret, error);
>  }
> +
> +int
> +rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item
> pattern[],
> +			 enum rte_flow_encap_hash_field dest_field, uint8_t
> hash_len,
> +			 uint8_t *hash, struct rte_flow_error *error)
> +{
> +	int ret;
> +	struct rte_eth_dev *dev;
> +	const struct rte_flow_ops *ops;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	ops = rte_flow_ops_get(port_id, error);
> +	if (!ops || !ops->flow_calc_encap_hash)
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> +					  "calc encap hash is not supported");
> +	if ((dest_field == RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT &&
> hash_len != 2) ||
> +	    (dest_field == RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID
> && hash_len != 1))
> +		return rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> +					  "hash len doesn't match the
> requested field len");
> +	dev = &rte_eth_devices[port_id];
> +	ret = ops->flow_calc_encap_hash(dev, pattern, dest_field, hash,
> error);
> +	return flow_err(port_id, ret, error);
> +}
> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
> index 1267c146e5..ffbde58245 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -6783,6 +6783,56 @@ rte_flow_calc_table_hash(uint16_t port_id, const
> struct rte_flow_template_table
>  			 const struct rte_flow_item pattern[], uint8_t
> pattern_template_index,
>  			 uint32_t *hash, struct rte_flow_error *error);
> 
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Destination field type for the hash calculation, when encap action is used.
> + *
> + * @see function rte_flow_calc_encap_hash
> + */
> +enum rte_flow_encap_hash_field {
> +	/* Calculate hash placed in UDP source port field. */
> +	RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT,
> +	/* Calculate hash placed in NVGRE flow ID field. */
> +	RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID,
> +};
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Simulates HW hash calculation that is done when encap action is being
> used.
> + *
> + * @param[in] port_id
> + *   Port identifier of Ethernet device.
> + * @param[in] pattern
> + *   The values to be used in the hash calculation.
> + * @param[in] dest_field
> + *   Type of destination field for hash calculation.
> + * @param[in] hash_len
> + *   The length of the hash pointer in bytes. Should be according to
> encap_hash_field.
> + * @param[out] hash
> + *   Used to return the calculated hash. It will be written in network order,
> + *   so hash[0] is the MSB.
> + *   The number of bytes is based on the destination field type.
> + * @param[out] error
> + *   Perform verbose error reporting if not NULL.
> + *   PMDs initialize this structure in case of error only.
> + *
> + * @return
> + *   - (0) if success.
> + *   - (-ENODEV) if *port_id* invalid.
> + *   - (-ENOTSUP) if underlying device does not support this functionality.
> + *   - (-EINVAL) if *pattern* doesn't hold enough information to calculate the
> hash
> + *               or the dest is not supported.
> + */
> +__rte_experimental
> +int
> +rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item
> pattern[],
> +			 enum rte_flow_encap_hash_field dest_field, uint8_t
> hash_len,
> +			 uint8_t *hash, struct rte_flow_error *error);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h
> index f35f659503..447163655a 100644
> --- a/lib/ethdev/rte_flow_driver.h
> +++ b/lib/ethdev/rte_flow_driver.h
> @@ -370,6 +370,11 @@ struct rte_flow_ops {
>  		(struct rte_eth_dev *dev, const struct
> rte_flow_template_table *table,
>  		 const struct rte_flow_item pattern[], uint8_t
> pattern_template_index,
>  		 uint32_t *hash, struct rte_flow_error *error);
> +	/** @see rte_flow_calc_encap_hash() */
> +	int (*flow_calc_encap_hash)
> +		(struct rte_eth_dev *dev, const struct rte_flow_item
> pattern[],
> +		 enum rte_flow_encap_hash_field dest_field, uint8_t *hash,
> +		 struct rte_flow_error *error);
>  };
> 
>  /**
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index a050baab0f..360898d067 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -319,6 +319,7 @@ EXPERIMENTAL {
> 
>  	# added in 24.03
>  	rte_eth_find_rss_algo;
> +	rte_flow_calc_encap_hash;
>  };
> 
>  INTERNAL {
> --
> 2.34.1
  
Thomas Monjalon Feb. 6, 2024, 10:39 p.m. UTC | #2
28/01/2024 10:39, Ori Kam:
> During the encapsulation of a packet, it is expected to calculate the
> hash value which is based on the original packet (the outer values,
> which will become the inner values).

It is not clear what the hash is for.

> The tunnel protocol defines which tunnel field should hold this hash,
> but it doesn't define the hash calculation algorithm.

If the hash is stored in the packet header,
I expect it to be reproducible when being checked.
How the algorithm may be undefined?

> An application that uses flow offloads gets the first few packets
> and then decides to offload the flow. As a result, there are two
> different paths that a packet from a given flow may take.
> SW for the first few packets or HW for the rest.
> When the packet goes through the SW, the SW encapsulates the packet
> and must use the same hash calculation as the HW will do for
> the rest of the packets in this flow.
> 
> This patch gives the SW a way to query the hash value
> for a given packet as if the packet was passed through the HW.
> 
> Signed-off-by: Ori Kam <orika@nvidia.com>
> ---
> +Calculate encap hash
> +~~~~~~~~~~~~~~~~~~~~
> +
> +Calculating hash of a packet in SW as it would be calculated in HW for the encap action

We should give the real full name of the flow action.

> +
> +When the HW execute an encapsulation action, it may calculate an hash value which is based
> +on the original packet. This hash is stored depending on the encapsulation protocol, in one
> +of the outer fields.

Give an example of such encapsulation protocol?

> +This function allows the application to calculate the hash for a given packet as if the
> +encapsulation was done in HW.
> +
> +.. code-block:: c
> +
> +   int
> +   rte_flow_calc_encap_hash(uint16_t port_id,
> +                            const struct rte_flow_item pattern[],
> +			                   enum rte_flow_encap_hash_field dest_field,
> +                            uint8_t hash_len,
> +                            uint8_t *hash,
> +			                   struct rte_flow_error *error);

I don't think we should add the complete prototype in this guide.

[...]
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Simulates HW hash calculation that is done when encap action is being used.

s/Simulates/Simulate/

> + *
> + * @param[in] port_id
> + *   Port identifier of Ethernet device.
> + * @param[in] pattern
> + *   The values to be used in the hash calculation.
> + * @param[in] dest_field
> + *   Type of destination field for hash calculation.
> + * @param[in] hash_len
> + *   The length of the hash pointer in bytes. Should be according to encap_hash_field.
> + * @param[out] hash
> + *   Used to return the calculated hash. It will be written in network order,
> + *   so hash[0] is the MSB.
> + *   The number of bytes is based on the destination field type.
> + * @param[out] error
> + *   Perform verbose error reporting if not NULL.
> + *   PMDs initialize this structure in case of error only.
> + *
> + * @return
> + *   - (0) if success.
> + *   - (-ENODEV) if *port_id* invalid.
> + *   - (-ENOTSUP) if underlying device does not support this functionality.
> + *   - (-EINVAL) if *pattern* doesn't hold enough information to calculate the hash
> + *               or the dest is not supported.
> + */
> +__rte_experimental
> +int
> +rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item pattern[],
> +			 enum rte_flow_encap_hash_field dest_field, uint8_t hash_len,
> +			 uint8_t *hash, struct rte_flow_error *error);
  
Ori Kam Feb. 7, 2024, 6:56 a.m. UTC | #3
Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Wednesday, February 7, 2024 12:40 AM
> 
> 28/01/2024 10:39, Ori Kam:
> > During the encapsulation of a packet, it is expected to calculate the
> > hash value which is based on the original packet (the outer values,
> > which will become the inner values).
> 
> It is not clear what the hash is for.

Will add explanation.

> 
> > The tunnel protocol defines which tunnel field should hold this hash,
> > but it doesn't define the hash calculation algorithm.
> 
> If the hash is stored in the packet header,
> I expect it to be reproducible when being checked.
> How the algorithm may be undefined?
> 
The hash is not being checked it is used for hash the packets to different queues.
the actual value is not important. It is critical that all packets that belongs to the same
flow will have the same hash value.

> > An application that uses flow offloads gets the first few packets
> > and then decides to offload the flow. As a result, there are two
> > different paths that a packet from a given flow may take.
> > SW for the first few packets or HW for the rest.
> > When the packet goes through the SW, the SW encapsulates the packet
> > and must use the same hash calculation as the HW will do for
> > the rest of the packets in this flow.
> >
> > This patch gives the SW a way to query the hash value
> > for a given packet as if the packet was passed through the HW.
> >
> > Signed-off-by: Ori Kam <orika@nvidia.com>
> > ---
> > +Calculate encap hash
> > +~~~~~~~~~~~~~~~~~~~~
> > +
> > +Calculating hash of a packet in SW as it would be calculated in HW for the
> encap action
> 
> We should give the real full name of the flow action.
> 
> > +
> > +When the HW execute an encapsulation action, it may calculate an hash
> value which is based
> > +on the original packet. This hash is stored depending on the encapsulation
> protocol, in one
> > +of the outer fields.
> 
> Give an example of such encapsulation protocol?

Sure,
Just to be clear something like this?
When the HW execute an encapsulation action for example for VXLAN tunnel,, it may ...

> 
> > +This function allows the application to calculate the hash for a given
> packet as if the
> > +encapsulation was done in HW.
> > +
> > +.. code-block:: c
> > +
> > +   int
> > +   rte_flow_calc_encap_hash(uint16_t port_id,
> > +                            const struct rte_flow_item pattern[],
> > +			                   enum rte_flow_encap_hash_field
> dest_field,
> > +                            uint8_t hash_len,
> > +                            uint8_t *hash,
> > +			                   struct rte_flow_error *error);
> 
> I don't think we should add the complete prototype in this guide.

Agree, will remove.

> 
> [...]
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change without prior notice.
> > + *
> > + * Simulates HW hash calculation that is done when encap action is being
> used.
> 
> s/Simulates/Simulate/

Will fix.
> 
> > + *
> > + * @param[in] port_id
> > + *   Port identifier of Ethernet device.
> > + * @param[in] pattern
> > + *   The values to be used in the hash calculation.
> > + * @param[in] dest_field
> > + *   Type of destination field for hash calculation.
> > + * @param[in] hash_len
> > + *   The length of the hash pointer in bytes. Should be according to
> encap_hash_field.
> > + * @param[out] hash
> > + *   Used to return the calculated hash. It will be written in network order,
> > + *   so hash[0] is the MSB.
> > + *   The number of bytes is based on the destination field type.
> > + * @param[out] error
> > + *   Perform verbose error reporting if not NULL.
> > + *   PMDs initialize this structure in case of error only.
> > + *
> > + * @return
> > + *   - (0) if success.
> > + *   - (-ENODEV) if *port_id* invalid.
> > + *   - (-ENOTSUP) if underlying device does not support this functionality.
> > + *   - (-EINVAL) if *pattern* doesn't hold enough information to calculate
> the hash
> > + *               or the dest is not supported.
> > + */
> > +__rte_experimental
> > +int
> > +rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item
> pattern[],
> > +			 enum rte_flow_encap_hash_field dest_field, uint8_t
> hash_len,
> > +			 uint8_t *hash, struct rte_flow_error *error);
> 
>
  
Thomas Monjalon Feb. 7, 2024, 9:25 a.m. UTC | #4
07/02/2024 07:56, Ori Kam:
> Hi Thomas,
> 
> > -----Original Message-----
> > From: Thomas Monjalon <thomas@monjalon.net>
> > Sent: Wednesday, February 7, 2024 12:40 AM
> > 
> > 28/01/2024 10:39, Ori Kam:
> > > During the encapsulation of a packet, it is expected to calculate the
> > > hash value which is based on the original packet (the outer values,
> > > which will become the inner values).
> > 
> > It is not clear what the hash is for.
> 
> Will add explanation.
> 
> > 
> > > The tunnel protocol defines which tunnel field should hold this hash,
> > > but it doesn't define the hash calculation algorithm.
> > 
> > If the hash is stored in the packet header,
> > I expect it to be reproducible when being checked.
> > How the algorithm may be undefined?
> > 
> The hash is not being checked it is used for hash the packets to different queues.
> the actual value is not important. It is critical that all packets that belongs to the same
> flow will have the same hash value.

That's the missing explanation.
Please describe you are talking about an internal hash
used for distributing packet in queues.
You should also explain how it differs from RSS.


> > > An application that uses flow offloads gets the first few packets
> > > and then decides to offload the flow. As a result, there are two
> > > different paths that a packet from a given flow may take.
> > > SW for the first few packets or HW for the rest.
> > > When the packet goes through the SW, the SW encapsulates the packet
> > > and must use the same hash calculation as the HW will do for
> > > the rest of the packets in this flow.
> > >
> > > This patch gives the SW a way to query the hash value
> > > for a given packet as if the packet was passed through the HW.
> > >
> > > Signed-off-by: Ori Kam <orika@nvidia.com>
> > > ---
> > > +Calculate encap hash
> > > +~~~~~~~~~~~~~~~~~~~~
> > > +
> > > +Calculating hash of a packet in SW as it would be calculated in HW for the
> > encap action
> > 
> > We should give the real full name of the flow action.
> > 
> > > +
> > > +When the HW execute an encapsulation action, it may calculate an hash
> > value which is based
> > > +on the original packet. This hash is stored depending on the encapsulation
> > protocol, in one
> > > +of the outer fields.
> > 
> > Give an example of such encapsulation protocol?
> 
> Sure,
> Just to be clear something like this?
> When the HW execute an encapsulation action for example for VXLAN tunnel,, it may ...

I was more thinking about saying which fields are hashed in VXLAN,
and more importantly how/when the hash is used.
  

Patch

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 900fdaefb6..0435dda3c7 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -4211,6 +4211,28 @@  as it would be calculated in the HW.
                             uint8_t pattern_template_index,
 			                   uint32_t *hash, struct rte_flow_error *error);
 
+Calculate encap hash
+~~~~~~~~~~~~~~~~~~~~
+
+Calculating hash of a packet in SW as it would be calculated in HW for the encap action
+
+When the HW execute an encapsulation action, it may calculate an hash value which is based
+on the original packet. This hash is stored depending on the encapsulation protocol, in one
+of the outer fields.
+
+This function allows the application to calculate the hash for a given packet as if the
+encapsulation was done in HW.
+
+.. code-block:: c
+
+   int
+   rte_flow_calc_encap_hash(uint16_t port_id,
+                            const struct rte_flow_item pattern[],
+			                   enum rte_flow_encap_hash_field dest_field,
+                            uint8_t hash_len,
+                            uint8_t *hash,
+			                   struct rte_flow_error *error);
+
 .. _flow_isolated_mode:
 
 Flow isolated mode
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 5e545da867..80af380172 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -75,6 +75,10 @@  New Features
   * Added support for VXLAN-GPE matching in HW Steering flow engine
     (``dv_flow_en`` = 2).
 
+* **Added ability to calculate the encap hash as done by HW.**
+
+  * Added function that calculates the encap hash, as the HW calculates it:
+    ``rte_flow_calc_encap_hash()``
 
 Removed Items
 -------------
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 3f58d792f9..7fce754be1 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -2482,3 +2482,28 @@  rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table
 					hash, error);
 	return flow_err(port_id, ret, error);
 }
+
+int
+rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item pattern[],
+			 enum rte_flow_encap_hash_field dest_field, uint8_t hash_len,
+			 uint8_t *hash, struct rte_flow_error *error)
+{
+	int ret;
+	struct rte_eth_dev *dev;
+	const struct rte_flow_ops *ops;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	ops = rte_flow_ops_get(port_id, error);
+	if (!ops || !ops->flow_calc_encap_hash)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "calc encap hash is not supported");
+	if ((dest_field == RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT && hash_len != 2) ||
+	    (dest_field == RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID && hash_len != 1))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "hash len doesn't match the requested field len");
+	dev = &rte_eth_devices[port_id];
+	ret = ops->flow_calc_encap_hash(dev, pattern, dest_field, hash, error);
+	return flow_err(port_id, ret, error);
+}
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 1267c146e5..ffbde58245 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -6783,6 +6783,56 @@  rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table
 			 const struct rte_flow_item pattern[], uint8_t pattern_template_index,
 			 uint32_t *hash, struct rte_flow_error *error);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destination field type for the hash calculation, when encap action is used.
+ *
+ * @see function rte_flow_calc_encap_hash
+ */
+enum rte_flow_encap_hash_field {
+	/* Calculate hash placed in UDP source port field. */
+	RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT,
+	/* Calculate hash placed in NVGRE flow ID field. */
+	RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID,
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Simulates HW hash calculation that is done when encap action is being used.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] pattern
+ *   The values to be used in the hash calculation.
+ * @param[in] dest_field
+ *   Type of destination field for hash calculation.
+ * @param[in] hash_len
+ *   The length of the hash pointer in bytes. Should be according to encap_hash_field.
+ * @param[out] hash
+ *   Used to return the calculated hash. It will be written in network order,
+ *   so hash[0] is the MSB.
+ *   The number of bytes is based on the destination field type.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOTSUP) if underlying device does not support this functionality.
+ *   - (-EINVAL) if *pattern* doesn't hold enough information to calculate the hash
+ *               or the dest is not supported.
+ */
+__rte_experimental
+int
+rte_flow_calc_encap_hash(uint16_t port_id, const struct rte_flow_item pattern[],
+			 enum rte_flow_encap_hash_field dest_field, uint8_t hash_len,
+			 uint8_t *hash, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h
index f35f659503..447163655a 100644
--- a/lib/ethdev/rte_flow_driver.h
+++ b/lib/ethdev/rte_flow_driver.h
@@ -370,6 +370,11 @@  struct rte_flow_ops {
 		(struct rte_eth_dev *dev, const struct rte_flow_template_table *table,
 		 const struct rte_flow_item pattern[], uint8_t pattern_template_index,
 		 uint32_t *hash, struct rte_flow_error *error);
+	/** @see rte_flow_calc_encap_hash() */
+	int (*flow_calc_encap_hash)
+		(struct rte_eth_dev *dev, const struct rte_flow_item pattern[],
+		 enum rte_flow_encap_hash_field dest_field, uint8_t *hash,
+		 struct rte_flow_error *error);
 };
 
 /**
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index a050baab0f..360898d067 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -319,6 +319,7 @@  EXPERIMENTAL {
 
 	# added in 24.03
 	rte_eth_find_rss_algo;
+	rte_flow_calc_encap_hash;
 };
 
 INTERNAL {