Hi Ferruh, Can you please review my patch?
Thanks, Ori > -----Original Message----- > From: Ori Kam <or...@nvidia.com> > Sent: Sunday, January 28, 2024 11:40 AM > To: Dariusz Sosnowski <dsosnow...@nvidia.com>; ferruh.yi...@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 <or...@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