Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Cavium, Inc
3 : : */
4 : :
5 : : #ifndef _TEST_PERF_COMMON_
6 : : #define _TEST_PERF_COMMON_
7 : :
8 : : #include <stdio.h>
9 : : #include <stdbool.h>
10 : : #include <unistd.h>
11 : :
12 : : #include <rte_cryptodev.h>
13 : : #include <rte_cycles.h>
14 : : #include <rte_ethdev.h>
15 : : #include <rte_event_crypto_adapter.h>
16 : : #include <rte_event_eth_rx_adapter.h>
17 : : #include <rte_event_eth_tx_adapter.h>
18 : : #include <rte_event_timer_adapter.h>
19 : : #include <rte_event_vector_adapter.h>
20 : : #include <rte_eventdev.h>
21 : : #include <rte_lcore.h>
22 : : #include <rte_malloc.h>
23 : : #include <rte_mempool.h>
24 : : #include <rte_prefetch.h>
25 : :
26 : : #include "evt_common.h"
27 : : #include "evt_options.h"
28 : : #include "evt_test.h"
29 : :
30 : : #define TEST_PERF_CA_ID 0
31 : : #define TEST_PERF_DA_ID 0
32 : :
33 : : struct test_perf;
34 : :
35 : : struct __rte_cache_aligned worker_data {
36 : : uint64_t processed_pkts;
37 : : uint64_t processed_vecs;
38 : : uint64_t latency;
39 : : uint8_t dev_id;
40 : : uint8_t port_id;
41 : : struct test_perf *t;
42 : : };
43 : :
44 : : struct crypto_adptr_data {
45 : : uint8_t cdev_id;
46 : : uint16_t cdev_qp_id;
47 : : void **crypto_sess;
48 : : };
49 : :
50 : : struct dma_adptr_data {
51 : : uint8_t dma_dev_id;
52 : : uint16_t vchan_id;
53 : : };
54 : :
55 : : struct vector_adptr_data {
56 : : struct rte_event_vector_adapter *vector_adptr;
57 : : };
58 : :
59 : : struct __rte_cache_aligned prod_data {
60 : : uint8_t dev_id;
61 : : uint8_t port_id;
62 : : uint8_t queue_id;
63 : : struct crypto_adptr_data ca;
64 : : struct dma_adptr_data da;
65 : : struct vector_adptr_data va;
66 : : struct test_perf *t;
67 : : };
68 : :
69 : : struct __rte_cache_aligned test_perf {
70 : : /* Don't change the offset of "done". Signal handler use this memory
71 : : * to terminate all lcores work.
72 : : */
73 : : int done;
74 : : uint64_t outstand_pkts;
75 : : uint8_t nb_workers;
76 : : enum evt_test_result result;
77 : : uint32_t nb_flows;
78 : : uint64_t nb_pkts;
79 : : struct rte_mempool *pool;
80 : : struct prod_data prod[EVT_MAX_PORTS];
81 : : struct worker_data worker[EVT_MAX_PORTS];
82 : : struct evt_options *opt;
83 : : alignas(RTE_CACHE_LINE_SIZE) uint8_t sched_type_list[EVT_MAX_STAGES];
84 : : alignas(RTE_CACHE_LINE_SIZE) struct rte_event_timer_adapter *timer_adptr[
85 : : RTE_EVENT_TIMER_ADAPTER_NUM_MAX];
86 : : struct rte_mempool *ca_op_pool;
87 : : struct rte_mempool *ca_sess_pool;
88 : : struct rte_mempool *ca_asym_sess_pool;
89 : : struct rte_mempool *ca_vector_pool;
90 : : };
91 : :
92 : : struct __rte_cache_aligned perf_elt {
93 : : union {
94 : : struct rte_event_timer tim;
95 : : struct {
96 : : char pad[offsetof(struct rte_event_timer, user_meta)];
97 : : uint64_t timestamp;
98 : : };
99 : : };
100 : : };
101 : :
102 : : #define BURST_SIZE 16
103 : : #define MAX_PROD_ENQ_BURST_SIZE 128
104 : :
105 : : #define PERF_WORKER_INIT\
106 : : struct worker_data *w = arg;\
107 : : struct test_perf *t = w->t;\
108 : : struct evt_options *opt = t->opt;\
109 : : const uint8_t dev = w->dev_id;\
110 : : const uint8_t port = w->port_id;\
111 : : const uint8_t prod_timer_type = \
112 : : opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR;\
113 : : uint8_t *const sched_type_list = &t->sched_type_list[0];\
114 : : const enum evt_prod_type prod_type = opt->prod_type;\
115 : : struct rte_mempool *const pool = t->pool;\
116 : : const uint8_t nb_stages = t->opt->nb_stages;\
117 : : const uint8_t laststage = nb_stages - 1;\
118 : : uint8_t cnt = 0;\
119 : : alignas(RTE_CACHE_LINE_SIZE) void *bufs[16];\
120 : : int const sz = RTE_DIM(bufs);\
121 : : uint8_t stage;\
122 : : struct perf_elt *pe = NULL;\
123 : : if (opt->verbose_level > 1)\
124 : : printf("%s(): lcore %d dev_id %d port=%d\n", __func__,\
125 : : rte_lcore_id(), dev, port)
126 : :
127 : : static __rte_always_inline void
128 : : perf_mark_fwd_latency(enum evt_prod_type prod_type, struct rte_event *const ev)
129 : : {
130 : : struct perf_elt *pe;
131 : :
132 : 0 : if (prod_type == EVT_PROD_TYPE_EVENT_CRYPTO_ADPTR) {
133 : 0 : struct rte_crypto_op *op = ev->event_ptr;
134 : : struct rte_mbuf *m;
135 : :
136 : 0 : if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
137 : 0 : if (op->sym->m_dst == NULL)
138 : 0 : m = op->sym->m_src;
139 : : else
140 : : m = op->sym->m_dst;
141 : :
142 : 0 : pe = rte_pktmbuf_mtod(m, struct perf_elt *);
143 : : } else {
144 : 0 : pe = RTE_PTR_ADD(op->asym->modex.result.data,
145 : : op->asym->modex.result.length);
146 : : }
147 : 0 : pe->timestamp = rte_get_timer_cycles();
148 : 0 : } else if (prod_type == EVT_PROD_TYPE_EVENT_DMA_ADPTR) {
149 : 0 : struct rte_event_dma_adapter_op *op = ev->event_ptr;
150 : :
151 : 0 : op->user_meta = rte_get_timer_cycles();
152 : : } else {
153 : 0 : pe = ev->event_ptr;
154 : 0 : pe->timestamp = rte_get_timer_cycles();
155 : : }
156 : : }
157 : :
158 : : static __rte_always_inline int
159 : : perf_handle_crypto_ev(struct rte_event *ev)
160 : : {
161 : 0 : struct rte_crypto_op *op = ev->event_ptr;
162 : :
163 : 0 : if (unlikely(op->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) {
164 : 0 : rte_crypto_op_free(op);
165 : 0 : return op->status;
166 : : }
167 : :
168 : : return 0;
169 : : }
170 : :
171 : : static __rte_always_inline struct perf_elt *
172 : : perf_elt_from_vec_get(struct rte_event_vector *vec)
173 : : {
174 : : /* Timestamp for vector event stored in first element */
175 : 0 : struct rte_crypto_op *cop = vec->ptrs[0];
176 : : struct rte_mbuf *m;
177 : :
178 : 0 : if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
179 : 0 : m = cop->sym->m_dst == NULL ? cop->sym->m_src : cop->sym->m_dst;
180 : 0 : return rte_pktmbuf_mtod(m, struct perf_elt *);
181 : : } else {
182 : 0 : return RTE_PTR_ADD(cop->asym->modex.result.data, cop->asym->modex.result.length);
183 : : }
184 : : }
185 : :
186 : : static __rte_always_inline int
187 : : perf_handle_crypto_vector_ev(struct rte_event *ev, struct perf_elt **pe,
188 : : const int enable_fwd_latency)
189 : : {
190 : 0 : struct rte_event_vector *vec = ev->vec;
191 : : struct rte_crypto_op *cop;
192 : : struct rte_mbuf *m;
193 : : int i, n = 0;
194 : : void *data;
195 : :
196 : 0 : for (i = 0; i < vec->nb_elem; i++) {
197 : 0 : cop = vec->ptrs[i];
198 : 0 : if (unlikely(cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) {
199 : 0 : if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
200 : 0 : m = cop->sym->m_dst == NULL ? cop->sym->m_src : cop->sym->m_dst;
201 : 0 : rte_pktmbuf_free(m);
202 : : } else {
203 : 0 : data = cop->asym->modex.result.data;
204 : 0 : rte_mempool_put(rte_mempool_from_obj(data), data);
205 : : }
206 : 0 : rte_crypto_op_free(cop);
207 : 0 : continue;
208 : : }
209 : 0 : vec->ptrs[n++] = cop;
210 : : }
211 : :
212 : : /* All cops failed, free the vector */
213 : 0 : if (n == 0) {
214 : 0 : rte_mempool_put(rte_mempool_from_obj(vec), vec);
215 : : return -ENOENT;
216 : : }
217 : :
218 : 0 : vec->nb_elem = n;
219 : :
220 : : /* Forward latency not enabled - perf data will be not accessed */
221 : 0 : if (!enable_fwd_latency)
222 : : return 0;
223 : :
224 : : /* Get pointer to perf data */
225 : : *pe = perf_elt_from_vec_get(vec);
226 : :
227 : : return 0;
228 : : }
229 : :
230 : : static __rte_always_inline int
231 : : perf_process_last_stage(struct rte_mempool *const pool, enum evt_prod_type prod_type,
232 : : struct rte_event *const ev, struct worker_data *const w,
233 : : void *bufs[], int const buf_sz, uint8_t count)
234 : : {
235 : : void *to_free_in_bulk;
236 : :
237 : : /* release fence here ensures event_prt is
238 : : * stored before updating the number of
239 : : * processed packets for worker lcores
240 : : */
241 : : rte_atomic_thread_fence(rte_memory_order_release);
242 : 0 : w->processed_pkts++;
243 : :
244 : 0 : if (prod_type == EVT_PROD_TYPE_EVENT_CRYPTO_ADPTR) {
245 : 0 : struct rte_crypto_op *op = ev->event_ptr;
246 : : struct rte_mbuf *m;
247 : :
248 : 0 : if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
249 : 0 : if (op->sym->m_dst == NULL)
250 : 0 : m = op->sym->m_src;
251 : : else
252 : : m = op->sym->m_dst;
253 : :
254 : : to_free_in_bulk = m;
255 : : } else {
256 : 0 : to_free_in_bulk = op->asym->modex.result.data;
257 : : }
258 : 0 : rte_crypto_op_free(op);
259 : : } else {
260 : 0 : to_free_in_bulk = ev->event_ptr;
261 : : }
262 : :
263 : 0 : bufs[count++] = to_free_in_bulk;
264 : 0 : if (unlikely(count == buf_sz)) {
265 : : count = 0;
266 : : rte_mempool_put_bulk(pool, bufs, buf_sz);
267 : : }
268 : :
269 : : return count;
270 : : }
271 : :
272 : : static __rte_always_inline uint8_t
273 : : perf_process_last_stage_latency(struct rte_mempool *const pool, enum evt_prod_type prod_type,
274 : : struct rte_event *const ev, struct worker_data *const w,
275 : : void *bufs[], int const buf_sz, uint8_t count)
276 : : {
277 : : uint64_t latency, tstamp;
278 : : struct perf_elt *pe;
279 : : void *to_free_in_bulk;
280 : :
281 : : /* Release fence here ensures event_prt is stored before updating the number of processed
282 : : * packets for worker lcores.
283 : : */
284 : : rte_atomic_thread_fence(rte_memory_order_release);
285 : 0 : w->processed_pkts++;
286 : :
287 : 0 : if (prod_type == EVT_PROD_TYPE_EVENT_CRYPTO_ADPTR) {
288 : 0 : struct rte_crypto_op *op = ev->event_ptr;
289 : : struct rte_mbuf *m;
290 : :
291 : 0 : if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
292 : 0 : if (op->sym->m_dst == NULL)
293 : 0 : m = op->sym->m_src;
294 : : else
295 : : m = op->sym->m_dst;
296 : :
297 : : to_free_in_bulk = m;
298 : 0 : pe = rte_pktmbuf_mtod(m, struct perf_elt *);
299 : : } else {
300 : 0 : pe = RTE_PTR_ADD(op->asym->modex.result.data,
301 : : op->asym->modex.result.length);
302 : : to_free_in_bulk = op->asym->modex.result.data;
303 : : }
304 : 0 : tstamp = pe->timestamp;
305 : 0 : rte_crypto_op_free(op);
306 : 0 : } else if (prod_type == EVT_PROD_TYPE_EVENT_DMA_ADPTR) {
307 : 0 : struct rte_event_dma_adapter_op *op = ev->event_ptr;
308 : :
309 : : to_free_in_bulk = op;
310 : 0 : tstamp = op->user_meta;
311 : : } else {
312 : 0 : pe = ev->event_ptr;
313 : 0 : tstamp = pe->timestamp;
314 : : to_free_in_bulk = pe;
315 : : }
316 : :
317 : 0 : latency = rte_get_timer_cycles() - tstamp;
318 : 0 : w->latency += latency;
319 : :
320 : 0 : bufs[count++] = to_free_in_bulk;
321 : 0 : if (unlikely(count == buf_sz)) {
322 : : count = 0;
323 : : rte_mempool_put_bulk(pool, bufs, buf_sz);
324 : : }
325 : :
326 : : return count;
327 : : }
328 : :
329 : : static __rte_always_inline void
330 : : perf_process_crypto_vector_last_stage(struct rte_mempool *const pool,
331 : : struct rte_mempool *const ca_pool, struct rte_event *const ev,
332 : : struct worker_data *const w, const bool enable_fwd_latency)
333 : 0 : {
334 : 0 : struct rte_event_vector *vec = ev->vec;
335 : : struct rte_crypto_op *cop;
336 : 0 : void *bufs[vec->nb_elem];
337 : : struct perf_elt *pe;
338 : : uint64_t latency;
339 : : int i;
340 : :
341 : : /* Release fence here ensures event_prt is stored before updating the number of processed
342 : : * packets for worker lcores.
343 : : */
344 : : rte_atomic_thread_fence(rte_memory_order_release);
345 : 0 : w->processed_pkts += vec->nb_elem;
346 : :
347 : 0 : if (enable_fwd_latency) {
348 : : pe = perf_elt_from_vec_get(vec);
349 : 0 : latency = rte_get_timer_cycles() - pe->timestamp;
350 : 0 : w->latency += latency;
351 : : }
352 : :
353 : 0 : for (i = 0; i < vec->nb_elem; i++) {
354 : 0 : cop = vec->ptrs[i];
355 : 0 : if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)
356 : 0 : bufs[i] = cop->sym->m_dst == NULL ? cop->sym->m_src : cop->sym->m_dst;
357 : : else
358 : 0 : bufs[i] = cop->asym->modex.result.data;
359 : : }
360 : :
361 : 0 : rte_mempool_put_bulk(pool, bufs, vec->nb_elem);
362 : 0 : rte_mempool_put_bulk(ca_pool, (void * const *)vec->ptrs, vec->nb_elem);
363 : 0 : rte_mempool_put(rte_mempool_from_obj(vec), vec);
364 : 0 : }
365 : :
366 : : static inline int
367 : : perf_nb_event_ports(struct evt_options *opt)
368 : : {
369 : 0 : return evt_nr_active_lcores(opt->wlcores) +
370 : 0 : evt_nr_active_lcores(opt->plcores);
371 : : }
372 : :
373 : : int perf_test_result(struct evt_test *test, struct evt_options *opt);
374 : : int perf_opt_check(struct evt_options *opt, uint64_t nb_queues);
375 : : int perf_test_setup(struct evt_test *test, struct evt_options *opt);
376 : : int perf_ethdev_setup(struct evt_test *test, struct evt_options *opt);
377 : : int perf_cryptodev_setup(struct evt_test *test, struct evt_options *opt);
378 : : int perf_dmadev_setup(struct evt_test *test, struct evt_options *opt);
379 : : int perf_mempool_setup(struct evt_test *test, struct evt_options *opt);
380 : : int perf_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
381 : : uint8_t stride, uint8_t nb_queues,
382 : : const struct rte_event_port_conf *port_conf);
383 : : int perf_event_dev_service_setup(uint8_t dev_id);
384 : : int perf_launch_lcores(struct evt_test *test, struct evt_options *opt,
385 : : int (*worker)(void *));
386 : : void perf_opt_dump(struct evt_options *opt, uint8_t nb_queues);
387 : : void perf_test_destroy(struct evt_test *test, struct evt_options *opt);
388 : : void perf_eventdev_destroy(struct evt_test *test, struct evt_options *opt);
389 : : void perf_cryptodev_destroy(struct evt_test *test, struct evt_options *opt);
390 : : void perf_dmadev_destroy(struct evt_test *test, struct evt_options *opt);
391 : : void perf_ethdev_destroy(struct evt_test *test, struct evt_options *opt);
392 : : void perf_ethdev_rx_stop(struct evt_test *test, struct evt_options *opt);
393 : : void perf_mempool_destroy(struct evt_test *test, struct evt_options *opt);
394 : : void perf_worker_cleanup(struct rte_mempool *const pool, uint8_t dev_id,
395 : : uint8_t port_id, struct rte_event events[],
396 : : uint16_t nb_enq, uint16_t nb_deq);
397 : :
398 : : #endif /* _TEST_PERF_COMMON_ */
|