new file mode 100644
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- SPDX-License-Identifier: BSD-3-Clause -->
+<!-- Copyright(c) 2022 NVIDIA Corporation & Affiliates -->
+
+<svg
+ width="485" height="535"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ overflow="hidden">
+ <defs>
+ <clipPath id="clip0">
+ <rect x="0" y="0" width="485" height="535"/>
+ </clipPath>
+ </defs>
+ <g clip-path="url(#clip0)">
+ <rect x="0" y="0" width="485" height="535" fill="#FFFFFF"/>
+ <rect x="0.500053" y="79.5001" width="482" height="59"
+ stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8"
+ fill="#A6A6A6"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(121.6 116)">
+ rte_eth_dev_configure
+ <tspan font-size="24" x="224.007" y="0">()</tspan>
+ </text>
+ <rect x="0.500053" y="158.5" width="482" height="59" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(140.273 195)">
+ rte_flow_configure()
+ </text>
+ <rect x="0.500053" y="236.5" width="482" height="60" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(77.4259 274)">
+ rte_flow_item_template_create()
+ </text>
+ <rect x="0.500053" y="316.5" width="482" height="59" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(69.3792 353)">
+ rte_flow_action_template_create
+ <tspan font-size="24" x="328.447" y="0">(</tspan>)
+ </text>
+ <rect x="0.500053" y="0.500053" width="482" height="60" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#A6A6A6"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(177.233 37)">
+ rte_eal_init
+ <tspan font-size="24" x="112.74" y="0">()</tspan>
+ </text>
+ <path d="M2-1.09108e-05 2.00005 9.2445-1.99995 9.24452-2 1.09108e-05ZM6.00004 7.24448 0.000104987 19.2445-5.99996 7.24455Z" transform="matrix(-1 0 0 1 241 60)"/>
+ <path d="M2-1.08133e-05 2.00005 9.41805-1.99995 9.41807-2 1.08133e-05ZM6.00004 7.41802 0.000104987 19.4181-5.99996 7.41809Z" transform="matrix(-1 0 0 1 241 138)"/>
+ <path d="M2-1.09108e-05 2.00005 9.2445-1.99995 9.24452-2 1.09108e-05ZM6.00004 7.24448 0.000104987 19.2445-5.99996 7.24455Z" transform="matrix(-1 0 0 1 241 217)"/>
+ <rect x="0.500053" y="395.5" width="482" height="59" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(124.989 432)">
+ rte_flow_table_create
+ <tspan font-size="24" x="217.227" y="0">(</tspan>
+ <tspan font-size="24" x="224.56" y="0">)</tspan>
+ </text>
+ <path d="M2-1.05859e-05 2.00005 9.83526-1.99995 9.83529-2 1.05859e-05ZM6.00004 7.83524 0.000104987 19.8353-5.99996 7.83531Z" transform="matrix(-1 0 0 1 241 296)"/>
+ <path d="M243 375 243 384.191 239 384.191 239 375ZM247 382.191 241 394.191 235 382.191Z"/>
+ <rect x="0.500053" y="473.5" width="482" height="60" stroke="#000000"
+ stroke-width="1.33333" stroke-miterlimit="8" fill="#A6A6A6"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif"
+ font-weight="400" font-size="24" transform="translate(145.303 511)">
+ rte_eth_dev_start()</text>
+ <path d="M245 454 245 463.191 241 463.191 241 454ZM249 461.191 243 473.191 237 461.191Z"/>
+ </g>
+</svg>
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- SPDX-License-Identifier: BSD-3-Clause -->
+<!-- Copyright(c) 2022 NVIDIA Corporation & Affiliates -->
+
+<svg
+ width="880" height="610"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ overflow="hidden">
+ <defs>
+ <clipPath id="clip0">
+ <rect x="0" y="0" width="880" height="610"/>
+ </clipPath>
+ </defs>
+ <g clip-path="url(#clip0)">
+ <rect x="0" y="0" width="880" height="610" fill="#FFFFFF"/>
+ <rect x="333.5" y="0.500053" width="234" height="45" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#A6A6A6"/>
+ <text font-family="Consolas,Consolas_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(357.196 29)">rte_eth_rx_burst()</text>
+ <rect x="333.5" y="63.5001" width="234" height="45" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(394.666 91)">analyze <tspan font-size="19" x="60.9267" y="0">packet </tspan></text>
+ <rect x="572.5" y="279.5" width="234" height="46" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(591.429 308)">rte_flow_q_create_flow()</text>
+ <path d="M333.5 384 450.5 350.5 567.5 384 450.5 417.5Z" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#D9D9D9" fill-rule="evenodd"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(430.069 378)">more <tspan font-size="19" x="-12.94" y="23">packets?</tspan></text>
+ <path d="M689.249 325.5 689.249 338.402 450.5 338.402 450.833 338.069 450.833 343.971 450.167 343.971 450.167 337.735 688.916 337.735 688.582 338.069 688.582 325.5ZM454.5 342.638 450.5 350.638 446.5 342.638Z"/>
+ <path d="M450.833 45.5 450.833 56.8197 450.167 56.8197 450.167 45.5001ZM454.5 55.4864 450.5 63.4864 446.5 55.4864Z"/>
+ <path d="M450.833 108.5 450.833 120.375 450.167 120.375 450.167 108.5ZM454.5 119.041 450.5 127.041 446.5 119.041Z"/>
+ <path d="M451.833 507.5 451.833 533.61 451.167 533.61 451.167 507.5ZM455.5 532.277 451.5 540.277 447.5 532.277Z"/>
+ <path d="M0 0.333333-23.9993 0.333333-23.666 0-23.666 141.649-23.9993 141.316 562.966 141.316 562.633 141.649 562.633 124.315 563.299 124.315 563.299 141.983-24.3327 141.983-24.3327-0.333333 0-0.333333ZM558.966 125.649 562.966 117.649 566.966 125.649Z" transform="matrix(-6.12323e-17 -1 -1 6.12323e-17 451.149 585.466)"/>
+ <path d="M333.5 160.5 450.5 126.5 567.5 160.5 450.5 194.5Z" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#D9D9D9" fill-rule="evenodd"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(417.576 155)">add new <tspan font-size="19" x="13.2867" y="23">rule?</tspan></text>
+ <path d="M567.5 160.167 689.267 160.167 689.267 273.228 688.6 273.228 688.6 160.5 688.933 160.833 567.5 160.833ZM692.933 271.894 688.933 279.894 684.933 271.894Z"/>
+ <rect x="602.5" y="127.5" width="46" height="30" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(611.34 148)">yes</text>
+ <rect x="254.5" y="126.5" width="46" height="31" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(267.182 147)">no</text>
+ <path d="M0-0.333333 251.563-0.333333 251.563 298.328 8.00002 298.328 8.00002 297.662 251.229 297.662 250.896 297.995 250.896 0 251.229 0.333333 0 0.333333ZM9.33333 301.995 1.33333 297.995 9.33333 293.995Z" transform="matrix(1 0 0 -1 567.5 383.495)"/>
+ <path d="M86.5001 213.5 203.5 180.5 320.5 213.5 203.5 246.5Z" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#D9D9D9" fill-rule="evenodd"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(159.155 208)">destroy the <tspan font-size="19" x="24.0333" y="23">rule?</tspan></text>
+ <path d="M0-0.333333 131.029-0.333333 131.029 12.9778 130.363 12.9778 130.363 0 130.696 0.333333 0 0.333333ZM134.696 11.6445 130.696 19.6445 126.696 11.6445Z" transform="matrix(-1 1.22465e-16 1.22465e-16 1 334.196 160.5)"/>
+ <rect x="81.5001" y="280.5" width="234" height="45" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(96.2282 308)">rte_flow_q_destroy_flow()</text>
+ <path d="M0 0.333333-24.0001 0.333333-23.6667 0-23.6667 49.9498-24.0001 49.6165 121.748 49.6165 121.748 59.958 121.082 59.958 121.082 49.9498 121.415 50.2832-24.3334 50.2832-24.3334-0.333333 0-0.333333ZM125.415 58.6247 121.415 66.6247 117.415 58.6247Z" transform="matrix(-1 0 0 1 319.915 213.5)"/>
+ <path d="M86.5001 213.833 62.5002 213.833 62.8335 213.5 62.8335 383.95 62.5002 383.617 327.511 383.617 327.511 384.283 62.1668 384.283 62.1668 213.167 86.5001 213.167ZM326.178 379.95 334.178 383.95 326.178 387.95Z"/>
+ <path d="M0-0.333333 12.8273-0.333333 12.8273 252.111 12.494 251.778 18.321 251.778 18.321 252.445 12.1607 252.445 12.1607 0 12.494 0.333333 0 0.333333ZM16.9877 248.111 24.9877 252.111 16.9877 256.111Z" transform="matrix(1.83697e-16 1 1 -1.83697e-16 198.5 325.5)"/>
+ <rect x="334.5" y="540.5" width="234" height="45" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(365.083 569)">rte_flow_q_dequeue<tspan font-size="19" x="160.227" y="0">()</tspan></text>
+ <rect x="334.5" y="462.5" width="234" height="45" stroke="#000000" stroke-width="1.33333" stroke-miterlimit="8" fill="#FFFFFF"/>
+ <text font-family="Calibri,Calibri_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(379.19 491)">rte_flow_q<tspan font-size="19" x="83.56" y="0">_drain</tspan>()</text>
+ <path d="M450.833 417.495 451.402 455.999 450.735 456.008 450.167 417.505ZM455.048 454.611 451.167 462.669 447.049 454.729Z"/>
+ <rect x="0.500053" y="287.5" width="46" height="30" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(12.8617 308)">no</text>
+ <rect x="357.5" y="223.5" width="47" height="31" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(367.001 244)">yes</text>
+ <rect x="469.5" y="421.5" width="46" height="30" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(481.872 442)">no</text>
+ <rect x="832.5" y="223.5" width="46" height="31" stroke="#000000" stroke-width="0.666667" stroke-miterlimit="8" fill="#D9D9D9"/>
+ <text font-family="Trebuchet MS,Trebuchet MS_MSFontService,sans-serif" font-weight="400" font-size="19" transform="translate(841.777 244)">yes</text>
+ </g>
+</svg>
\ No newline at end of file
@@ -3607,18 +3607,22 @@ Hints about the 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.
+It also creates flow queues for asynchronous flow rules operations via
+queue-based API, see `Asynchronous operations`_ section.
.. code-block:: c
int
rte_flow_configure(uint16_t port_id,
const struct rte_flow_port_attr *port_attr,
+ const struct rte_flow_queue_attr *queue_attr[],
struct rte_flow_error *error);
Arguments:
- ``port_id``: port identifier of Ethernet device.
- ``port_attr``: port attributes for flow management library.
+- ``queue_attr``: queue attributes for asynchronous operations.
- ``error``: perform verbose error reporting if not NULL. PMDs initialize
this structure in case of error only.
@@ -3750,6 +3754,160 @@ and item and action templates are created.
*at, nb_action_templates,
*error);
+Asynchronous operations
+-----------------------
+
+Flow rules creation/destruction can be done by using lockless flow queues.
+An application configures the number of queues during the initialization stage.
+Then create/destroy operations are enqueued without any locks asynchronously.
+By adopting an asynchronous queue-based approach, the packet processing can
+continue with handling next packets while insertion/destruction of a flow rule
+is processed inside the hardware. The application is expected to poll for
+results later to see if the flow rule is successfully inserted/destroyed.
+User data is returned as part of the result to identify the enqueued operation.
+Polling must be done before the queue is overflowed or periodically.
+Operations can be reordered inside a queue, so the result of the rule creation
+needs to be polled first before enqueueing the destroy operation for the rule.
+Flow handle is valid once the create operation is enqueued and must be
+destroyed even if the operation is not successful and the rule is not inserted.
+
+The asynchronous flow rule insertion logic can be broken into two phases.
+
+1. Initialization stage as shown here:
+
+.. _figure_rte_flow_q_init:
+
+.. figure:: img/rte_flow_q_init.*
+
+2. Main loop as presented on a datapath application example:
+
+.. _figure_rte_flow_q_usage:
+
+.. figure:: img/rte_flow_q_usage.*
+
+Enqueue creation operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Enqueueing a flow rule creation operation is similar to simple creation.
+
+.. code-block:: c
+
+ struct rte_flow *
+ rte_flow_q_flow_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_table *table,
+ const struct rte_flow_item items[],
+ uint8_t item_template_index,
+ const struct rte_flow_action actions[],
+ uint8_t action_template_index,
+ struct rte_flow_error *error);
+
+A valid handle in case of success is returned. It must be destroyed later
+by calling ``rte_flow_q_flow_destroy()`` even if the rule is rejected by HW.
+
+Enqueue destruction operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Enqueueing a flow rule destruction operation is similar to simple destruction.
+
+.. code-block:: c
+
+ int
+ rte_flow_q_flow_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow *flow,
+ struct rte_flow_error *error);
+
+Drain a queue
+~~~~~~~~~~~~~
+
+Function to drain the queue and push all internally stored rules to the NIC.
+
+.. code-block:: c
+
+ int
+ rte_flow_q_drain(uint16_t port_id,
+ uint32_t queue_id,
+ struct rte_flow_error *error);
+
+There is the drain attribute in the queue operation attributes.
+When set, the requested operation must be sent to the HW without any delay.
+If not, multiple operations can be bulked together and not sent to HW right
+away to save SW/HW interactions and prioritize throughput over latency.
+The application must invoke this function to actually push all outstanding
+operations to HW in the latter case.
+
+Dequeue operations
+~~~~~~~~~~~~~~~~~~
+
+Dequeue rte flow operations.
+
+The application must invoke this function in order to complete the asynchronous
+flow rule operation and to receive the flow rule operation status.
+
+.. code-block:: c
+
+ int
+ rte_flow_q_dequeue(uint16_t port_id,
+ uint32_t queue_id,
+ struct rte_flow_q_op_res res[],
+ uint16_t n_res,
+ struct rte_flow_error *error);
+
+Multiple outstanding operations can be dequeued simultaneously.
+User data may be provided during a flow creation/destruction in order
+to distinguish between multiple operations. User data is returned as part
+of the result to provide a method to detect which operation is completed.
+
+Enqueue indirect action creation operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Asynchronous version of indirect action creation API.
+
+.. code-block:: c
+
+ struct rte_flow_action_handle *
+ rte_flow_q_action_handle_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ const struct rte_flow_indir_action_conf *indir_action_conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error);
+
+A valid handle in case of success is returned. It must be destroyed later by
+calling ``rte_flow_q_action_handle_destroy()`` even if the rule is rejected.
+
+Enqueue indirect action destruction operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Asynchronous version of indirect action destruction API.
+
+.. code-block:: c
+
+ int
+ rte_flow_q_action_handle_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ struct rte_flow_error *error);
+
+Enqueue indirect action update operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Asynchronous version of indirect action update API.
+
+.. code-block:: c
+
+ int
+ rte_flow_q_action_handle_update(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ const void *update,
+ struct rte_flow_error *error);
+
.. _flow_isolated_mode:
Flow isolated mode
@@ -66,6 +66,15 @@ New Features
``rte_flow_table_destroy``, ``rte_flow_item_template_destroy``
and ``rte_flow_action_template_destroy`` respectively.
+* ethdev: Added ``rte_flow_q_flow_create`` and ``rte_flow_q_flow_destroy`` API
+ to enqueue flow creaion/destruction operations asynchronously as well as
+ ``rte_flow_q_dequeue`` to poll results of these operations and
+ ``rte_flow_q_drain`` to drain the flow queue and pass all operations to NIC.
+ Introduced asynchronous API for indirect actions management as well:
+ ``rte_flow_q_action_handle_create``, ``rte_flow_q_action_handle_destroy`` and
+ ``rte_flow_q_action_handle_update``.
+
+
Removed Items
-------------
@@ -1395,6 +1395,7 @@ rte_flow_flex_item_release(uint16_t port_id,
int
rte_flow_configure(uint16_t port_id,
const struct rte_flow_port_attr *port_attr,
+ const struct rte_flow_queue_attr *queue_attr[],
struct rte_flow_error *error)
{
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
@@ -1404,7 +1405,8 @@ rte_flow_configure(uint16_t port_id,
return -rte_errno;
if (likely(!!ops->configure)) {
return flow_err(port_id,
- ops->configure(dev, port_attr, error),
+ ops->configure(dev, port_attr,
+ queue_attr, error),
error);
}
return rte_flow_error_set(error, ENOTSUP,
@@ -1552,3 +1554,172 @@ rte_flow_table_destroy(uint16_t port_id,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, rte_strerror(ENOTSUP));
}
+
+struct rte_flow *
+rte_flow_q_flow_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_table *table,
+ const struct rte_flow_item items[],
+ uint8_t item_template_index,
+ const struct rte_flow_action actions[],
+ uint8_t action_template_index,
+ 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);
+ struct rte_flow *flow;
+
+ if (unlikely(!ops))
+ return NULL;
+ if (likely(!!ops->q_flow_create)) {
+ flow = ops->q_flow_create(dev, queue_id, q_ops_attr, table,
+ items, item_template_index,
+ actions, action_template_index,
+ error);
+ if (flow == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return flow;
+ }
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+ return NULL;
+}
+
+int
+rte_flow_q_flow_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow *flow,
+ 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->q_flow_destroy)) {
+ return flow_err(port_id,
+ ops->q_flow_destroy(dev, queue_id,
+ q_ops_attr, flow, error),
+ error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
+
+struct rte_flow_action_handle *
+rte_flow_q_action_handle_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ const struct rte_flow_indir_action_conf *indir_action_conf,
+ const struct rte_flow_action *action,
+ 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);
+ struct rte_flow_action_handle *handle;
+
+ if (unlikely(!ops))
+ return NULL;
+ if (unlikely(!ops->q_action_handle_create)) {
+ rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ rte_strerror(ENOSYS));
+ return NULL;
+ }
+ handle = ops->q_action_handle_create(dev, queue_id, q_ops_attr,
+ indir_action_conf, action, error);
+ if (handle == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return handle;
+}
+
+int
+rte_flow_q_action_handle_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ 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);
+ int ret;
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (unlikely(!ops->q_action_handle_destroy))
+ return rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+ ret = ops->q_action_handle_destroy(dev, queue_id, q_ops_attr,
+ action_handle, error);
+ return flow_err(port_id, ret, error);
+}
+
+int
+rte_flow_q_action_handle_update(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ const void *update,
+ 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);
+ int ret;
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (unlikely(!ops->q_action_handle_update))
+ return rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+ ret = ops->q_action_handle_update(dev, queue_id, q_ops_attr,
+ action_handle, update, error);
+ return flow_err(port_id, ret, error);
+}
+
+int
+rte_flow_q_drain(uint16_t port_id,
+ uint32_t queue_id,
+ 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->q_drain)) {
+ return flow_err(port_id,
+ ops->q_drain(dev, queue_id, error),
+ error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
+
+int
+rte_flow_q_dequeue(uint16_t port_id,
+ uint32_t queue_id,
+ struct rte_flow_q_op_res res[],
+ uint16_t n_res,
+ 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);
+ int ret;
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (likely(!!ops->q_dequeue)) {
+ ret = ops->q_dequeue(dev, queue_id, res, n_res, error);
+ return ret ? ret : flow_err(port_id, ret, error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
@@ -4865,6 +4865,13 @@ struct rte_flow_port_attr {
* Version of the struct layout, should be 0.
*/
uint32_t version;
+ /**
+ * Number of flow queues to be configured.
+ * Flow queues are used for asynchronous flow rule operations.
+ * The order of operations is not guaranteed inside a queue.
+ * Flow queues are not thread-safe.
+ */
+ uint16_t nb_queues;
/**
* Number of counter actions pre-configured.
* If set to 0, PMD will allocate counters dynamically.
@@ -4885,6 +4892,21 @@ struct rte_flow_port_attr {
uint32_t nb_meters;
};
+/**
+ * Flow engine queue configuration.
+ */
+__extension__
+struct rte_flow_queue_attr {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /**
+ * Number of flow rule operations a queue can hold.
+ */
+ uint32_t size;
+};
+
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice.
@@ -4903,6 +4925,9 @@ struct rte_flow_port_attr {
* Port identifier of Ethernet device.
* @param[in] port_attr
* Port configuration attributes.
+ * @param[in] queue_attr
+ * Array that holds attributes for each flow queue.
+ * Number of elements is set in @p port_attr.nb_queues.
* @param[out] error
* Perform verbose error reporting if not NULL.
* PMDs initialize this structure in case of error only.
@@ -4914,6 +4939,7 @@ __rte_experimental
int
rte_flow_configure(uint16_t port_id,
const struct rte_flow_port_attr *port_attr,
+ const struct rte_flow_queue_attr *queue_attr[],
struct rte_flow_error *error);
/**
@@ -5185,6 +5211,328 @@ rte_flow_table_destroy(uint16_t port_id,
struct rte_flow_table *table,
struct rte_flow_error *error);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Queue operation attributes.
+ */
+struct rte_flow_q_ops_attr {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /**
+ * The user data that will be returned on the completion events.
+ */
+ void *user_data;
+ /**
+ * When set, the requested action must be sent to the HW without
+ * any delay. Any prior requests must be also sent to the HW.
+ * If this bit is cleared, the application must call the
+ * rte_flow_queue_drain API to actually send the request to the HW.
+ */
+ uint32_t drain:1;
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue rule creation operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param queue_id
+ * Flow queue used to insert the rule.
+ * @param[in] q_ops_attr
+ * Rule creation operation attributes.
+ * @param[in] table
+ * Table to select templates from.
+ * @param[in] items
+ * List of pattern items to be used.
+ * The list order should match the order in the item template.
+ * The spec is the only relevant member of the item that is being used.
+ * @param[in] item_template_index
+ * Item template index in the table.
+ * @param[in] actions
+ * List of actions to be used.
+ * The list order should match the order in the action template.
+ * @param[in] action_template_index
+ * Action template index in the table.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * Handle on success, NULL otherwise and rte_errno is set.
+ * The rule handle doesn't mean that the rule was offloaded.
+ * Only completion result indicates that the rule was offloaded.
+ */
+__rte_experimental
+struct rte_flow *
+rte_flow_q_flow_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_table *table,
+ const struct rte_flow_item items[],
+ uint8_t item_template_index,
+ const struct rte_flow_action actions[],
+ uint8_t action_template_index,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue rule destruction operation.
+ *
+ * This function enqueues a destruction operation on the queue.
+ * Application should assume that after calling this function
+ * the rule handle is not valid anymore.
+ * Completion indicates the full removal of the rule from the HW.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param queue_id
+ * Flow queue which is used to destroy the rule.
+ * This must match the queue on which the rule was created.
+ * @param[in] q_ops_attr
+ * Rule destroy operation attributes.
+ * @param[in] flow
+ * Flow handle to be destroyed.
+ * @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_q_flow_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow *flow,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action creation operation.
+ * @see rte_flow_action_handle_create
+ *
+ * @param[in] port_id
+ * Port identifier of Ethernet device.
+ * @param[in] queue_id
+ * Flow queue which is used to create the rule.
+ * @param[in] q_ops_attr
+ * Queue operation attributes.
+ * @param[in] indir_action_conf
+ * Action configuration for the indirect action object creation.
+ * @param[in] action
+ * Specific configuration of the indirect action object.
+ * @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.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if action pointed by *action* handle was not found.
+ * - (-EBUSY) if action pointed by *action* handle still used by some rules
+ * rte_errno is also set.
+ */
+__rte_experimental
+struct rte_flow_action_handle *
+rte_flow_q_action_handle_create(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ const struct rte_flow_indir_action_conf *indir_action_conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ * Port identifier of Ethernet device.
+ * @param[in] queue_id
+ * Flow queue which is used to destroy the rule.
+ * @param[in] q_ops_attr
+ * Queue operation attributes.
+ * @param[in] action_handle
+ * Handle for the indirect action object to be destroyed.
+ * @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.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if action pointed by *action* handle was not found.
+ * - (-EBUSY) if action pointed by *action* handle still used by some rules
+ * rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_q_action_handle_destroy(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action update operation.
+ * @see rte_flow_action_handle_create
+ *
+ * @param[in] port_id
+ * Port identifier of Ethernet device.
+ * @param[in] queue_id
+ * Flow queue which is used to update the rule.
+ * @param[in] q_ops_attr
+ * Queue operation attributes.
+ * @param[in] action_handle
+ * Handle for the indirect action object to be updated.
+ * @param[in] update
+ * Update profile specification used to modify the action pointed by handle.
+ * *update* could be with the same type of the immediate action corresponding
+ * to the *handle* argument when creating, or a wrapper structure includes
+ * action configuration to be updated and bit fields to indicate the member
+ * of fields inside the action to update.
+ * @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.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if action pointed by *action* handle was not found.
+ * - (-EBUSY) if action pointed by *action* handle still used by some rules
+ * rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_q_action_handle_update(uint16_t port_id,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ const void *update,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Drain the queue and push all internally stored rules to the HW.
+ * Non-drained rules are rules that were inserted without the drain flag set.
+ * Can be used to notify the HW about batch of rules prepared by the SW to
+ * reduce the number of communications between the HW and SW.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param queue_id
+ * Flow queue to be drained.
+ * @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_q_drain(uint16_t port_id,
+ uint32_t queue_id,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Dequeue operation status.
+ */
+enum rte_flow_q_op_status {
+ /**
+ * The operation was completed successfully.
+ */
+ RTE_FLOW_Q_OP_SUCCESS,
+ /**
+ * The operation was not completed successfully.
+ */
+ RTE_FLOW_Q_OP_ERROR,
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Queue operation attributes
+ */
+__extension__
+struct rte_flow_q_op_res {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /**
+ * Returns the status of the operation that this completion signals.
+ */
+ enum rte_flow_q_op_status status;
+ /**
+ * The user data that will be returned on the completion events.
+ */
+ void *user_data;
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Dequeue a rte flow operation.
+ * The application must invoke this function in order to complete
+ * the flow rule offloading and to receive the flow rule operation status.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param queue_id
+ * Flow queue which is used to dequeue the operation.
+ * @param[out] res
+ * Array of results that will be set.
+ * @param[in] n_res
+ * Maximum number of results that can be returned.
+ * This value is equal to the size of the res array.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * Number of results that were dequeued,
+ * a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_q_dequeue(uint16_t port_id,
+ uint32_t queue_id,
+ struct rte_flow_q_op_res res[],
+ uint16_t n_res,
+ struct rte_flow_error *error);
+
#ifdef __cplusplus
}
#endif
@@ -156,6 +156,7 @@ struct rte_flow_ops {
int (*configure)
(struct rte_eth_dev *dev,
const struct rte_flow_port_attr *port_attr,
+ const struct rte_flow_queue_attr *queue_attr[],
struct rte_flow_error *err);
/** See rte_flow_item_template_create() */
struct rte_flow_item_template *(*item_template_create)
@@ -194,6 +195,66 @@ struct rte_flow_ops {
(struct rte_eth_dev *dev,
struct rte_flow_table *table,
struct rte_flow_error *err);
+ /** See rte_flow_q_flow_create() */
+ struct rte_flow *(*q_flow_create)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_table *table,
+ const struct rte_flow_item items[],
+ uint8_t item_template_index,
+ const struct rte_flow_action actions[],
+ uint8_t action_template_index,
+ struct rte_flow_error *err);
+ /** See rte_flow_q_flow_destroy() */
+ int (*q_flow_destroy)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow *flow,
+ struct rte_flow_error *err);
+ /** See rte_flow_q_flow_update() */
+ int (*q_flow_update)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow *flow,
+ struct rte_flow_error *err);
+ /** See rte_flow_q_action_handle_create() */
+ struct rte_flow_action_handle *(*q_action_handle_create)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ const struct rte_flow_indir_action_conf *indir_action_conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *err);
+ /** See rte_flow_q_action_handle_destroy() */
+ int (*q_action_handle_destroy)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ struct rte_flow_error *error);
+ /** See rte_flow_q_action_handle_update() */
+ int (*q_action_handle_update)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ const struct rte_flow_q_ops_attr *q_ops_attr,
+ struct rte_flow_action_handle *action_handle,
+ const void *update,
+ struct rte_flow_error *error);
+ /** See rte_flow_q_drain() */
+ int (*q_drain)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ struct rte_flow_error *err);
+ /** See rte_flow_q_dequeue() */
+ int (*q_dequeue)
+ (struct rte_eth_dev *dev,
+ uint32_t queue_id,
+ struct rte_flow_q_op_res res[],
+ uint16_t n_res,
+ struct rte_flow_error *error);
};
/**
@@ -265,6 +265,13 @@ EXPERIMENTAL {
rte_flow_action_template_destroy;
rte_flow_table_create;
rte_flow_table_destroy;
+ rte_flow_q_flow_create;
+ rte_flow_q_flow_destroy;
+ rte_flow_q_action_handle_create;
+ rte_flow_q_action_handle_destroy;
+ rte_flow_q_action_handle_update;
+ rte_flow_q_drain;
+ rte_flow_q_dequeue;
};
INTERNAL {