1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2018 Intel Corporation. All rights reserved.
3
4Event Crypto Adapter Library
5============================
6
7The DPDK :doc:`Eventdev library <eventdev>` provides event driven
8programming model with features to schedule events.
9The :doc:`Cryptodev library <cryptodev_lib>` provides an interface to
10the crypto poll mode drivers which supports different crypto operations.
11The Event Crypto Adapter is one of the adapter which is intended to
12bridge between the event device and the crypto device.
13
14The packet flow from crypto device to the event device can be accomplished
15using SW and HW based transfer mechanism.
16The Adapter queries an eventdev PMD to determine which mechanism to be used.
17The adapter uses an EAL service core function for SW based packet transfer
18and uses the eventdev PMD functions to configure HW based packet transfer
19between the crypto device and the event device. The crypto adapter uses a new
20event type called ``RTE_EVENT_TYPE_CRYPTODEV`` to indicate the event source.
21
22The application can choose to submit a crypto operation directly to
23crypto device or send it to the crypto adapter via eventdev based on
24RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD capability.
25The first mode is known as the event new(RTE_EVENT_CRYPTO_ADAPTER_OP_NEW)
26mode and the second as the event forward(RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD)
27mode. The choice of mode can be specified while creating the adapter.
28In the former mode, it is an application responsibility to enable ingress
29packet ordering. In the latter mode, it is the adapter responsibility to
30enable the ingress packet ordering.
31
32
33Adapter Mode
34------------
35
36RTE_EVENT_CRYPTO_ADAPTER_OP_NEW mode
37~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
39In the RTE_EVENT_CRYPTO_ADAPTER_OP_NEW mode, application submits crypto
40operations directly to crypto device. The adapter then dequeues crypto
41completions from crypto device and enqueues them as events to the event device.
42This mode does not ensure ingress ordering, if the application directly
43enqueues to the cryptodev without going through crypto/atomic stage.
44In this mode, events dequeued from the adapter will be treated as new events.
45The application needs to specify event information (response information)
46which is needed to enqueue an event after the crypto operation is completed.
47
48.. _figure_event_crypto_adapter_op_new:
49
50.. figure:: img/event_crypto_adapter_op_new.*
51
52   Working model of ``RTE_EVENT_CRYPTO_ADAPTER_OP_NEW`` mode
53
54
55RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD mode
56~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57
58In the RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD mode, if HW supports
59RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD capability the application
60can directly submit the crypto operations to the cryptodev.
61If not, application retrieves crypto adapter's event port using
62rte_event_crypto_adapter_event_port_get() API. Then, links its event
63queue to this port and starts enqueuing crypto operations as events
64to the eventdev. The adapter then dequeues the events and submits the
65crypto operations to the cryptodev. After the crypto completions, the
66adapter enqueues events to the event device.
67Application can use this mode, when ingress packet ordering is needed.
68In this mode, events dequeued from the adapter will be treated as
69forwarded events. The application needs to specify the cryptodev ID
70and queue pair ID (request information) needed to enqueue a crypto
71operation in addition to the event information (response information)
72needed to enqueue an event after the crypto operation has completed.
73
74.. _figure_event_crypto_adapter_op_forward:
75
76.. figure:: img/event_crypto_adapter_op_forward.*
77
78   Working model of ``RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD`` mode
79
80
81API Overview
82------------
83
84This section has a brief introduction to the event crypto adapter APIs.
85The application is expected to create an adapter which is associated with
86a single eventdev, then add cryptodev and queue pair to the adapter instance.
87
88Create an adapter instance
89~~~~~~~~~~~~~~~~~~~~~~~~~~
90
91An adapter instance is created using ``rte_event_crypto_adapter_create()``. This
92function is called with event device to be associated with the adapter and port
93configuration for the adapter to setup an event port(if the adapter needs to use
94a service function).
95
96Adapter can be started in ``RTE_EVENT_CRYPTO_ADAPTER_OP_NEW`` or
97``RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD`` mode.
98
99.. code-block:: c
100
101        int err;
102        uint8_t dev_id, id;
103        struct rte_event_dev_info dev_info;
104        struct rte_event_port_conf conf;
105        enum rte_event_crypto_adapter_mode mode;
106
107        err = rte_event_dev_info_get(id, &dev_info);
108
109        conf.new_event_threshold = dev_info.max_num_events;
110        conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
111        conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
112	mode = RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD;
113        err = rte_event_crypto_adapter_create(id, dev_id, &conf, mode);
114
115If the application desires to have finer control of eventdev port allocation
116and setup, it can use the ``rte_event_crypto_adapter_create_ext()`` function.
117The ``rte_event_crypto_adapter_create_ext()`` function is passed as a callback
118function. The callback function is invoked if the adapter needs to use a
119service function and needs to create an event port for it. The callback is
120expected to fill the ``struct rte_event_crypto_adapter_conf`` structure
121passed to it.
122
123For RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD mode, the event port created by adapter
124can be retrieved using ``rte_event_crypto_adapter_event_port_get()`` API.
125Application can use this event port to link with event queue on which it
126enqueues events towards the crypto adapter.
127
128.. code-block:: c
129
130        uint8_t id, evdev, crypto_ev_port_id, app_qid;
131        struct rte_event ev;
132        int ret;
133
134        ret = rte_event_crypto_adapter_event_port_get(id, &crypto_ev_port_id);
135        ret = rte_event_queue_setup(evdev, app_qid, NULL);
136        ret = rte_event_port_link(evdev, crypto_ev_port_id, &app_qid, NULL, 1);
137
138        // Fill in event info and update event_ptr with rte_crypto_op
139        memset(&ev, 0, sizeof(ev));
140        ev.queue_id = app_qid;
141        .
142        .
143        ev.event_ptr = op;
144        ret = rte_event_enqueue_burst(evdev, app_ev_port_id, ev, nb_events);
145
146Querying adapter capabilities
147~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148
149The ``rte_event_crypto_adapter_caps_get()`` function allows
150the application to query the adapter capabilities for an eventdev and cryptodev
151combination. This API provides whether cryptodev and eventdev are connected using
152internal HW port or not.
153
154.. code-block:: c
155
156        rte_event_crypto_adapter_caps_get(dev_id, cdev_id, &cap);
157
158Adding queue pair to the adapter instance
159~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160
161Cryptodev device id and queue pair are created using cryptodev APIs.
162For more information see :doc:`here  <cryptodev_lib>`.
163
164.. code-block:: c
165
166        struct rte_cryptodev_config conf;
167        struct rte_cryptodev_qp_conf qp_conf;
168        uint8_t cdev_id = 0;
169        uint16_t qp_id = 0;
170
171        rte_cryptodev_configure(cdev_id, &conf);
172        rte_cryptodev_queue_pair_setup(cdev_id, qp_id, &qp_conf);
173
174These cryptodev id and queue pair are added to the instance using the
175``rte_event_crypto_adapter_queue_pair_add()`` API.
176The same is removed using ``rte_event_crypto_adapter_queue_pair_del()`` API.
177If HW supports RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_QP_EV_BIND
178capability, event information must be passed to the add API.
179
180.. code-block:: c
181
182        uint32_t cap;
183        int ret;
184
185        ret = rte_event_crypto_adapter_caps_get(id, evdev, &cap);
186        if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_QP_EV_BIND) {
187                struct rte_event event;
188
189                // Fill in event information & pass it to add API
190                rte_event_crypto_adapter_queue_pair_add(id, cdev_id, qp_id, &event);
191        } else
192                rte_event_crypto_adapter_queue_pair_add(id, cdev_id, qp_id, NULL);
193
194Configure the service function
195~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196
197If the adapter uses a service function, the application is required to assign
198a service core to the service function as show below.
199
200.. code-block:: c
201
202        uint32_t service_id;
203
204        if (rte_event_crypto_adapter_service_id_get(id, &service_id) == 0)
205                rte_service_map_lcore_set(service_id, CORE_ID);
206
207Set event request/response information
208~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
209
210In the RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD mode, the application needs
211to specify the cryptodev ID and queue pair ID (request information) in
212addition to the event information (response information) needed to enqueue
213an event after the crypto operation has completed. The request and response
214information are specified in the ``struct rte_crypto_op`` private data or
215session's private data.
216
217In the RTE_EVENT_CRYPTO_ADAPTER_OP_NEW mode, the application is required
218to provide only the response information.
219
220The SW adapter or HW PMD uses ``rte_crypto_op::sess_type`` to
221decide whether request/response data is located in the crypto session/
222crypto security session or at an offset in the ``struct rte_crypto_op``.
223The ``rte_crypto_op::private_data_offset`` is used to locate the request/
224response in the ``rte_crypto_op``.
225
226For crypto session, ``rte_cryptodev_sym_session_set_user_data()`` API
227will be used to set request/response data. The same data will be obtained
228by ``rte_cryptodev_sym_session_get_user_data()`` API.  The
229RTE_EVENT_CRYPTO_ADAPTER_CAP_SESSION_PRIVATE_DATA capability indicates
230whether HW or SW supports this feature.
231
232For security session, ``rte_security_session_set_private_data()`` API
233will be used to set request/response data. The same data will be obtained
234by ``rte_security_session_get_private_data()`` API.
235
236For session-less it is mandatory to place the request/response data with
237the ``rte_crypto_op``.
238
239.. code-block:: c
240
241        union rte_event_crypto_metadata m_data;
242        struct rte_event ev;
243        struct rte_crypto_op *op;
244
245        /* Allocate & fill op structure */
246        op = rte_crypto_op_alloc();
247
248        memset(&m_data, 0, sizeof(m_data));
249        memset(&ev, 0, sizeof(ev));
250        /* Fill event information and update event_ptr to rte_crypto_op */
251        ev.event_ptr = op;
252
253        if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
254                /* Copy response information */
255                rte_memcpy(&m_data.response_info, &ev, sizeof(ev));
256                /* Copy request information */
257                m_data.request_info.cdev_id = cdev_id;
258                m_data.request_info.queue_pair_id = qp_id;
259                /* Call set API to store private data information */
260                rte_cryptodev_sym_session_set_user_data(
261                        op->sym->session,
262                        &m_data,
263                        sizeof(m_data));
264        } if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
265                uint32_t len = IV_OFFSET + MAXIMUM_IV_LENGTH +
266                               (sizeof(struct rte_crypto_sym_xform) * 2);
267                op->private_data_offset = len;
268                /* Copy response information */
269                rte_memcpy(&m_data.response_info, &ev, sizeof(ev));
270                /* Copy request information */
271                m_data.request_info.cdev_id = cdev_id;
272                m_data.request_info.queue_pair_id = qp_id;
273                /* Store private data information along with rte_crypto_op */
274                rte_memcpy(op + len, &m_data, sizeof(m_data));
275        }
276
277Start the adapter instance
278~~~~~~~~~~~~~~~~~~~~~~~~~~
279
280The application calls ``rte_event_crypto_adapter_start()`` to start the adapter.
281This function calls the start callbacks of the eventdev PMDs for hardware based
282eventdev-cryptodev connections and ``rte_service_run_state_set()`` to enable the
283service function if one exists.
284
285.. code-block:: c
286
287        rte_event_crypto_adapter_start(id, mode);
288
289.. Note::
290
291         The eventdev to which the event_crypto_adapter is connected needs to
292         be started before calling rte_event_crypto_adapter_start().
293
294Get adapter statistics
295~~~~~~~~~~~~~~~~~~~~~~
296
297The  ``rte_event_crypto_adapter_stats_get()`` function reports counters defined
298in struct ``rte_event_crypto_adapter_stats``. The received packet and
299enqueued event counts are a sum of the counts from the eventdev PMD callbacks
300if the callback is supported, and the counts maintained by the service function,
301if one exists.
302