On Friday, February 11, 2022 5:17 Andrew Rybchenko <andrew.rybche...@oktetlabs.ru> wrote: > Sent: Friday, February 11, 2022 5:17 > To: Alexander Kozyrev <akozy...@nvidia.com>; dev@dpdk.org > Cc: Ori Kam <or...@nvidia.com>; NBU-Contact-Thomas Monjalon (EXTERNAL) > <tho...@monjalon.net>; ivan.ma...@oktetlabs.ru; ferruh.yi...@intel.com; > mohammad.abdul.a...@intel.com; qi.z.zh...@intel.com; jer...@marvell.com; > ajit.khapa...@broadcom.com; bruce.richard...@intel.com > Subject: Re: [PATCH v5 01/10] ethdev: introduce flow pre-configuration hints > > On 2/11/22 05:26, Alexander Kozyrev wrote: > > The flow rules creation/destruction at a large scale incurs a performance > > penalty and may negatively impact the packet processing when used > > as part of the datapath logic. This is mainly because software/hardware > > resources are allocated and prepared during the flow rule creation. > > > > In order to optimize the insertion rate, PMD may use some hints provided > > by the application at the initialization phase. The rte_flow_configure() > > function allows to pre-allocate all the needed resources beforehand. > > These resources can be used at a later stage without costly allocations. > > Every PMD may use only the subset of hints and ignore unused ones or > > fail in case the requested configuration is not supported. > > > > The rte_flow_info_get() is available to retrieve the information about > > supported pre-configurable resources. Both these functions must be called > > before any other usage of the flow API engine. > > > > Signed-off-by: Alexander Kozyrev <akozy...@nvidia.com> > > Acked-by: Ori Kam <or...@nvidia.com> > > --- > > doc/guides/prog_guide/rte_flow.rst | 37 +++++++++ > > doc/guides/rel_notes/release_22_03.rst | 6 ++ > > lib/ethdev/rte_flow.c | 40 +++++++++ > > lib/ethdev/rte_flow.h | 108 +++++++++++++++++++++++++ > > lib/ethdev/rte_flow_driver.h | 10 +++ > > lib/ethdev/version.map | 2 + > > 6 files changed, 203 insertions(+) > > > > diff --git a/doc/guides/prog_guide/rte_flow.rst > b/doc/guides/prog_guide/rte_flow.rst > > index b4aa9c47c2..72fb1132ac 100644 > > --- a/doc/guides/prog_guide/rte_flow.rst > > +++ b/doc/guides/prog_guide/rte_flow.rst > > @@ -3589,6 +3589,43 @@ Return values: > > > > - 0 on success, a negative errno value otherwise and ``rte_errno`` is set. > > > > +Flow engine configuration > > +------------------------- > > + > > +Configure flow API management. > > + > > +An application may provide some parameters at the initialization phase > > about > > +rules engine configuration and/or expected flow rules characteristics. > > +These parameters may be used by PMD to preallocate resources and > configure NIC. > > + > > +Configuration > > +~~~~~~~~~~~~~ > > + > > +This function performs the flow API management configuration and > > +pre-allocates needed resources beforehand to avoid costly allocations > > later. > > +Expected number of counters or meters in an application, for example, > > +allow PMD to prepare and optimize NIC memory layout in advance. > > +``rte_flow_configure()`` must be called before any flow rule is created, > > +but after an Ethernet device is configured. > > + > > +.. code-block:: c > > + > > + int > > + rte_flow_configure(uint16_t port_id, > > + const struct rte_flow_port_attr *port_attr, > > + struct rte_flow_error *error); > > + > > +Information about resources that can benefit from pre-allocation can be > > +retrieved via ``rte_flow_info_get()`` API. It returns the maximum number > > +of pre-configurable resources for a given port on a system. > > + > > +.. code-block:: c > > + > > + int > > + rte_flow_info_get(uint16_t port_id, > > + struct rte_flow_port_info *port_info, > > + struct rte_flow_error *error); > > + > > .. _flow_isolated_mode: > > > > Flow isolated mode > > diff --git a/doc/guides/rel_notes/release_22_03.rst > b/doc/guides/rel_notes/release_22_03.rst > > index f03183ee86..2a47a37f0a 100644 > > --- a/doc/guides/rel_notes/release_22_03.rst > > +++ b/doc/guides/rel_notes/release_22_03.rst > > @@ -69,6 +69,12 @@ New Features > > New APIs, ``rte_eth_dev_priority_flow_ctrl_queue_info_get()`` and > > ``rte_eth_dev_priority_flow_ctrl_queue_configure()``, was added. > > > > +* ** Added functions to configure Flow API engine > > + > > + * ethdev: Added ``rte_flow_configure`` API to configure Flow Management > > + engine, allowing to pre-allocate some resources for better performance. > > + Added ``rte_flow_info_get`` API to retrieve pre-configurable resources. > > + > > * **Updated AF_XDP PMD** > > > > * Added support for libxdp >=v1.2.2. > > diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c > > index a93f68abbc..66614ae29b 100644 > > --- a/lib/ethdev/rte_flow.c > > +++ b/lib/ethdev/rte_flow.c > > @@ -1391,3 +1391,43 @@ rte_flow_flex_item_release(uint16_t port_id, > > ret = ops->flex_item_release(dev, handle, error); > > return flow_err(port_id, ret, error); > > } > > + > > +int > > +rte_flow_info_get(uint16_t port_id, > > + struct rte_flow_port_info *port_info, > > + struct rte_flow_error *error) > > +{ > > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > > + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); > > + > > + if (unlikely(!ops)) > > + return -rte_errno; > > + if (likely(!!ops->info_get)) { > > expected ethdev state must be validated. Just configured? > > > + return flow_err(port_id, > > + ops->info_get(dev, port_info, error), > > port_info must be checked vs NULL
We don’t have any NULL checks for parameters in the whole ret flow API library. See rte_flow_create() for example. attributes, pattern and actions are passed to PMD unchecked. > > + error); > > + } > > + return rte_flow_error_set(error, ENOTSUP, > > + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, > > + NULL, rte_strerror(ENOTSUP)); > > +} > > + > > +int > > +rte_flow_configure(uint16_t port_id, > > + const struct rte_flow_port_attr *port_attr, > > + struct rte_flow_error *error) > > +{ > > + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; > > + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); > > + > > + if (unlikely(!ops)) > > + return -rte_errno; > > + if (likely(!!ops->configure)) { > > The API must validate ethdev state. configured and not started? Again, we have no such validation for any rte flow API today. > > > + return flow_err(port_id, > > + ops->configure(dev, port_attr, error), > > port_attr must be checked vs NULL Same. > > + error); > > + } > > + return rte_flow_error_set(error, ENOTSUP, > > + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, > > + NULL, rte_strerror(ENOTSUP)); > > +} > > diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h > > index 1031fb246b..92be2a9a89 100644 > > --- a/lib/ethdev/rte_flow.h > > +++ b/lib/ethdev/rte_flow.h > > @@ -4853,6 +4853,114 @@ rte_flow_flex_item_release(uint16_t port_id, > > const struct rte_flow_item_flex_handle *handle, > > struct rte_flow_error *error); > > > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice. > > + * > > + * Information about available pre-configurable resources. > > + * The zero value means a resource cannot be pre-allocated. > > + * > > + */ > > +struct rte_flow_port_info { > > + /** > > + * Number of pre-configurable counter actions. > > + * @see RTE_FLOW_ACTION_TYPE_COUNT > > + */ > > + uint32_t nb_counters; > > Name says that it is a number of counters, but description > says that it is about actions. > Also I don't understand what does "pre-configurable" mean. > Isn't it a maximum number of available counters? > If no, how can I find a maximum? It is number of pre-allocated and pre-configured actions. How are they pr-configured is up to PDM driver. But let's change to "pre-configured" everywhere. Configuration includes some memory allocation anyway. > > > + /** > > + * Number of pre-configurable aging flows actions. > > + * @see RTE_FLOW_ACTION_TYPE_AGE > > + */ > > + uint32_t nb_aging_flows; > > Same Ditto. > > + /** > > + * Number of pre-configurable traffic metering actions. > > + * @see RTE_FLOW_ACTION_TYPE_METER > > + */ > > + uint32_t nb_meters; > > Same Ditto. > > +}; > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice. > > + * > > + * Retrieve configuration attributes supported by the port. > > Description should be a bit more flow API aware. > Right now it sounds too generic. Ok, how about "Get information about flow engine pre-configurable resources." > > + * > > + * @param port_id > > + * Port identifier of Ethernet device. > > + * @param[out] port_info > > + * A pointer to a structure of type *rte_flow_port_info* > > + * to be filled with the contextual information of the port. > > + * @param[out] error > > + * Perform verbose error reporting if not NULL. > > + * PMDs initialize this structure in case of error only. > > + * > > + * @return > > + * 0 on success, a negative errno value otherwise and rte_errno is set. > > + */ > > +__rte_experimental > > +int > > +rte_flow_info_get(uint16_t port_id, > > + struct rte_flow_port_info *port_info, > > + struct rte_flow_error *error); > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice. > > + * > > + * Resource pre-allocation and pre-configuration settings. > > What is the difference between pre-allocation and pre-configuration? > Why are both mentioned above, but just pre-configured actions are > mentioned below? Please see answer to this question above. > > + * The zero value means on demand resource allocations only. > > + * > > + */ > > +struct rte_flow_port_attr { > > + /** > > + * Number of counter actions pre-configured. > > + * @see RTE_FLOW_ACTION_TYPE_COUNT > > + */ > > + uint32_t nb_counters; > > + /** > > + * Number of aging flows actions pre-configured. > > + * @see RTE_FLOW_ACTION_TYPE_AGE > > + */ > > + uint32_t nb_aging_flows; > > + /** > > + * Number of traffic metering actions pre-configured. > > + * @see RTE_FLOW_ACTION_TYPE_METER > > + */ > > + uint32_t nb_meters; > > +}; > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice. > > + * > > + * Configure the port's flow API engine. > > + * > > + * This API can only be invoked before the application > > + * starts using the rest of the flow library functions. > > + * > > + * The API can be invoked multiple times to change the > > + * settings. The port, however, may reject the changes. > > + * > > + * Parameters in configuration attributes must not exceed > > + * numbers of resources returned by the rte_flow_info_get API. > > + * > > + * @param port_id > > + * Port identifier of Ethernet device. > > + * @param[in] port_attr > > + * Port configuration attributes. > > + * @param[out] error > > + * Perform verbose error reporting if not NULL. > > + * PMDs initialize this structure in case of error only. > > + * > > + * @return > > + * 0 on success, a negative errno value otherwise and rte_errno is set. > > + */ > > +__rte_experimental > > +int > > +rte_flow_configure(uint16_t port_id, > > + const struct rte_flow_port_attr *port_attr, > > + 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 f691b04af4..7c29930d0f 100644 > > --- a/lib/ethdev/rte_flow_driver.h > > +++ b/lib/ethdev/rte_flow_driver.h > > @@ -152,6 +152,16 @@ struct rte_flow_ops { > > (struct rte_eth_dev *dev, > > const struct rte_flow_item_flex_handle *handle, > > struct rte_flow_error *error); > > + /** See rte_flow_info_get() */ > > + int (*info_get) > > + (struct rte_eth_dev *dev, > > + struct rte_flow_port_info *port_info, > > + struct rte_flow_error *err); > > + /** See rte_flow_configure() */ > > + int (*configure) > > + (struct rte_eth_dev *dev, > > + const struct rte_flow_port_attr *port_attr, > > + struct rte_flow_error *err); > > }; > > > > /** > > diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map > > index cd0c4c428d..f1235aa913 100644 > > --- a/lib/ethdev/version.map > > +++ b/lib/ethdev/version.map > > @@ -260,6 +260,8 @@ EXPERIMENTAL { > > # added in 22.03 > > rte_eth_dev_priority_flow_ctrl_queue_configure; > > rte_eth_dev_priority_flow_ctrl_queue_info_get; > > + rte_flow_info_get; > > + rte_flow_configure; > > }; > > > > INTERNAL {