Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2017 Cavium, Inc.
3 : : */
4 : :
5 : : #include "test_pipeline_common.h"
6 : :
7 : : int
8 : 0 : pipeline_test_result(struct evt_test *test, struct evt_options *opt)
9 : : {
10 : : RTE_SET_USED(opt);
11 : : int i;
12 : : uint64_t total = 0;
13 : : struct test_pipeline *t = evt_test_priv(test);
14 : :
15 : 0 : evt_info("Packet distribution across worker cores :");
16 : 0 : for (i = 0; i < t->nb_workers; i++)
17 : 0 : total += t->worker[i].processed_pkts;
18 : 0 : for (i = 0; i < t->nb_workers; i++)
19 : 0 : evt_info("Worker %d packets: "CLGRN"%"PRIx64""CLNRM" percentage:"
20 : : CLGRN" %3.2f"CLNRM, i,
21 : : t->worker[i].processed_pkts,
22 : : (((double)t->worker[i].processed_pkts)/total)
23 : : * 100);
24 : 0 : return t->result;
25 : : }
26 : :
27 : : void
28 : 0 : pipeline_opt_dump(struct evt_options *opt, uint8_t nb_queues)
29 : : {
30 : 0 : evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
31 : 0 : evt_dump_worker_lcores(opt);
32 : : evt_dump_nb_stages(opt);
33 : : evt_dump("nb_evdev_ports", "%d", pipeline_nb_event_ports(opt));
34 : 0 : evt_dump("nb_evdev_queues", "%d", nb_queues);
35 : 0 : evt_dump_queue_priority(opt);
36 : 0 : evt_dump_sched_type_list(opt);
37 : 0 : evt_dump_producer_type(opt);
38 : 0 : evt_dump("nb_eth_rx_queues", "%d", opt->eth_queues);
39 : 0 : evt_dump("event_vector", "%d", opt->ena_vector);
40 : 0 : if (opt->ena_vector) {
41 : 0 : evt_dump("vector_size", "%d", opt->vector_size);
42 : 0 : evt_dump("vector_tmo_ns", "%" PRIu64 "", opt->vector_tmo_nsec);
43 : : }
44 : 0 : }
45 : :
46 : : static inline uint64_t
47 : : processed_pkts(struct test_pipeline *t)
48 : : {
49 : : uint8_t i;
50 : : uint64_t total = 0;
51 : :
52 : 0 : for (i = 0; i < t->nb_workers; i++)
53 : 0 : total += t->worker[i].processed_pkts;
54 : :
55 : : return total;
56 : : }
57 : :
58 : : /* RFC863 discard port */
59 : : #define UDP_SRC_PORT 9
60 : : #define UDP_DST_PORT 9
61 : :
62 : : /* RFC2544 reserved test subnet 192.18.0.0 */
63 : : #define IP_SRC_ADDR(x, y) ((192U << 24) | (18 << 16) | ((x) << 8) | (y))
64 : : #define IP_DST_ADDR(x, y) ((192U << 24) | (18 << 16) | ((x) << 8) | (y))
65 : :
66 : : #define IP_DEFTTL 64 /* from RFC 1340. */
67 : : #define IP_VERSION 0x40
68 : : #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */
69 : : #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
70 : :
71 : : static void
72 : 0 : setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
73 : : struct rte_udp_hdr *udp_hdr, uint16_t pkt_data_len,
74 : : uint8_t port, uint8_t flow)
75 : : {
76 : : uint16_t pkt_len;
77 : :
78 : : /*
79 : : * Initialize UDP header.
80 : : */
81 : 0 : pkt_len = (uint16_t)(pkt_data_len + sizeof(struct rte_udp_hdr));
82 : 0 : udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT);
83 : 0 : udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT);
84 : 0 : udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
85 : 0 : udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
86 : :
87 : : /*
88 : : * Initialize IP header.
89 : : */
90 : 0 : pkt_len = (uint16_t)(pkt_len + sizeof(struct rte_ipv4_hdr));
91 : 0 : ip_hdr->version_ihl = IP_VHL_DEF;
92 : 0 : ip_hdr->type_of_service = 0;
93 : 0 : ip_hdr->fragment_offset = 0;
94 : 0 : ip_hdr->time_to_live = IP_DEFTTL;
95 : 0 : ip_hdr->next_proto_id = IPPROTO_UDP;
96 : 0 : ip_hdr->packet_id = 0;
97 : 0 : ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
98 : 0 : ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR(port, 1));
99 : 0 : ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR(port + 1, flow));
100 : :
101 : : /*
102 : : * Compute IP header checksum.
103 : : */
104 : 0 : ip_hdr->hdr_checksum = rte_ipv4_cksum_simple(ip_hdr);
105 : 0 : }
106 : :
107 : : static void
108 : 0 : pipeline_tx_first(struct test_pipeline *t, struct evt_options *opt)
109 : : {
110 : : #define TX_DEF_PACKET_LEN 64
111 : : uint16_t eth_port_id = 0;
112 : : uint16_t pkt_sz, rc;
113 : : uint32_t i;
114 : :
115 : 0 : pkt_sz = opt->tx_pkt_sz;
116 : 0 : if (pkt_sz > opt->max_pkt_sz)
117 : 0 : pkt_sz = opt->max_pkt_sz;
118 : 0 : if (!pkt_sz)
119 : : pkt_sz = TX_DEF_PACKET_LEN;
120 : :
121 : 0 : RTE_ETH_FOREACH_DEV(eth_port_id) {
122 : : struct rte_ether_addr src_mac;
123 : : struct rte_ether_addr dst_mac;
124 : : struct rte_ether_hdr eth_hdr;
125 : :
126 : : /* Send to the same dest.mac as port mac */
127 : 0 : rte_eth_macaddr_get(eth_port_id, &dst_mac);
128 : 0 : rte_eth_random_addr((uint8_t *)&src_mac);
129 : :
130 : : rte_ether_addr_copy(&dst_mac, ð_hdr.dst_addr);
131 : : rte_ether_addr_copy(&src_mac, ð_hdr.src_addr);
132 : 0 : eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
133 : :
134 : 0 : for (i = 0; i < opt->tx_first; i++) {
135 : : struct rte_udp_hdr *pkt_udp_hdr;
136 : : struct rte_ipv4_hdr ip_hdr;
137 : : struct rte_udp_hdr udp_hdr;
138 : : struct rte_mbuf *mbuf;
139 : :
140 : 0 : mbuf = rte_pktmbuf_alloc(
141 : 0 : opt->per_port_pool ? t->pool[i] : t->pool[0]);
142 : 0 : if (mbuf == NULL)
143 : 0 : continue;
144 : :
145 : 0 : setup_pkt_udp_ip_headers(
146 : : &ip_hdr, &udp_hdr,
147 : : pkt_sz - sizeof(struct rte_ether_hdr) -
148 : 0 : sizeof(struct rte_ipv4_hdr) -
149 : : sizeof(struct rte_udp_hdr),
150 : : eth_port_id, i);
151 : 0 : mbuf->port = eth_port_id;
152 : 0 : mbuf->data_len = pkt_sz;
153 : 0 : mbuf->pkt_len = pkt_sz;
154 : :
155 : : /* Copy Ethernet header */
156 : 0 : rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, char *, 0),
157 : : ð_hdr, sizeof(struct rte_ether_hdr));
158 : :
159 : : /* Copy Ipv4 header */
160 : 0 : rte_memcpy(rte_pktmbuf_mtod_offset(
161 : : mbuf, char *,
162 : : sizeof(struct rte_ether_hdr)),
163 : : &ip_hdr, sizeof(struct rte_ipv4_hdr));
164 : :
165 : : /* Copy UDP header */
166 : 0 : rte_memcpy(
167 : 0 : rte_pktmbuf_mtod_offset(
168 : : mbuf, char *,
169 : : sizeof(struct rte_ipv4_hdr) +
170 : : sizeof(struct rte_ether_hdr)),
171 : : &udp_hdr, sizeof(struct rte_udp_hdr));
172 : 0 : pkt_udp_hdr = rte_pktmbuf_mtod_offset(
173 : : mbuf, struct rte_udp_hdr *,
174 : : sizeof(struct rte_ipv4_hdr) +
175 : : sizeof(struct rte_ether_hdr));
176 : 0 : pkt_udp_hdr->src_port =
177 : 0 : rte_cpu_to_be_16(UDP_SRC_PORT + i);
178 : 0 : pkt_udp_hdr->dst_port =
179 : 0 : rte_cpu_to_be_16(UDP_SRC_PORT + i);
180 : :
181 : 0 : rc = rte_eth_tx_burst(eth_port_id, 0, &mbuf, 1);
182 : 0 : if (rc == 0)
183 : 0 : rte_pktmbuf_free(mbuf);
184 : : }
185 : : }
186 : 0 : }
187 : :
188 : : int
189 : 0 : pipeline_launch_lcores(struct evt_test *test, struct evt_options *opt,
190 : : int (*worker)(void *))
191 : : {
192 : : struct test_pipeline *t = evt_test_priv(test);
193 : : int ret, lcore_id;
194 : : int port_idx = 0;
195 : :
196 : 0 : if (opt->tx_first)
197 : 0 : pipeline_tx_first(t, opt);
198 : :
199 : : /* launch workers */
200 : 0 : RTE_LCORE_FOREACH_WORKER(lcore_id) {
201 : 0 : if (!(opt->wlcores[lcore_id]))
202 : 0 : continue;
203 : :
204 : 0 : ret = rte_eal_remote_launch(worker,
205 : 0 : &t->worker[port_idx], lcore_id);
206 : 0 : if (ret) {
207 : 0 : evt_err("failed to launch worker %d", lcore_id);
208 : 0 : return ret;
209 : : }
210 : 0 : port_idx++;
211 : : }
212 : :
213 : : uint64_t perf_cycles = rte_get_timer_cycles();
214 : : const uint64_t perf_sample = rte_get_timer_hz();
215 : :
216 : : static float total_mpps;
217 : : static uint64_t samples;
218 : :
219 : : uint64_t prev_pkts = 0;
220 : :
221 : 0 : while (t->done == false) {
222 : : const uint64_t new_cycles = rte_get_timer_cycles();
223 : :
224 : 0 : if ((new_cycles - perf_cycles) > perf_sample) {
225 : : const uint64_t curr_pkts = processed_pkts(t);
226 : :
227 : 0 : float mpps = (float)(curr_pkts - prev_pkts)/1000000;
228 : :
229 : : prev_pkts = curr_pkts;
230 : : perf_cycles = new_cycles;
231 : 0 : total_mpps += mpps;
232 : 0 : ++samples;
233 : 0 : printf(CLGRN"\r%.3f mpps avg %.3f mpps"CLNRM,
234 : 0 : mpps, total_mpps/samples);
235 : 0 : fflush(stdout);
236 : : }
237 : : }
238 : : printf("\n");
239 : 0 : return 0;
240 : : }
241 : :
242 : : int
243 : 0 : pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues)
244 : : {
245 : : unsigned int lcores;
246 : :
247 : : /* N worker + main */
248 : : lcores = 2;
249 : :
250 : 0 : if (opt->prod_type != EVT_PROD_TYPE_ETH_RX_ADPTR) {
251 : 0 : evt_err("Invalid producer type '%s' valid producer '%s'",
252 : : evt_prod_id_to_name(opt->prod_type),
253 : : evt_prod_id_to_name(EVT_PROD_TYPE_ETH_RX_ADPTR));
254 : 0 : return -1;
255 : : }
256 : :
257 : 0 : if (!rte_eth_dev_count_avail()) {
258 : 0 : evt_err("test needs minimum 1 ethernet dev");
259 : 0 : return -1;
260 : : }
261 : :
262 : 0 : if (rte_lcore_count() < lcores) {
263 : 0 : evt_err("test need minimum %d lcores", lcores);
264 : 0 : return -1;
265 : : }
266 : :
267 : : /* Validate worker lcores */
268 : 0 : if (evt_lcores_has_overlap(opt->wlcores, rte_get_main_lcore())) {
269 : 0 : evt_err("worker lcores overlaps with main lcore");
270 : 0 : return -1;
271 : : }
272 : 0 : if (evt_has_disabled_lcore(opt->wlcores)) {
273 : 0 : evt_err("one or more workers lcores are not enabled");
274 : 0 : return -1;
275 : : }
276 : 0 : if (!evt_has_active_lcore(opt->wlcores)) {
277 : 0 : evt_err("minimum one worker is required");
278 : 0 : return -1;
279 : : }
280 : :
281 : 0 : if (nb_queues > EVT_MAX_QUEUES) {
282 : 0 : evt_err("number of queues exceeds %d", EVT_MAX_QUEUES);
283 : 0 : return -1;
284 : : }
285 : 0 : if (pipeline_nb_event_ports(opt) > EVT_MAX_PORTS) {
286 : 0 : evt_err("number of ports exceeds %d", EVT_MAX_PORTS);
287 : 0 : return -1;
288 : : }
289 : :
290 : 0 : if (opt->prod_type != EVT_PROD_TYPE_ETH_RX_ADPTR) {
291 : 0 : evt_err("Invalid producer type, only --prod_type_ethdev is supported");
292 : 0 : return -1;
293 : : }
294 : :
295 : 0 : if (evt_has_invalid_stage(opt))
296 : : return -1;
297 : :
298 : 0 : if (evt_has_invalid_sched_type(opt))
299 : 0 : return -1;
300 : :
301 : : return 0;
302 : : }
303 : :
304 : : #define NB_RX_DESC 128
305 : : #define NB_TX_DESC 512
306 : : int
307 : 0 : pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt)
308 : : {
309 : : uint16_t i, j;
310 : : int ret;
311 : : uint8_t nb_queues = 1;
312 : : struct test_pipeline *t = evt_test_priv(test);
313 : : struct rte_eth_rxconf rx_conf;
314 : 0 : struct rte_eth_conf port_conf = {
315 : : .rxmode = {
316 : : .mq_mode = RTE_ETH_MQ_RX_RSS,
317 : : },
318 : : .rx_adv_conf = {
319 : : .rss_conf = {
320 : : .rss_key = NULL,
321 : : .rss_hf = RTE_ETH_RSS_IP,
322 : : },
323 : : },
324 : : };
325 : :
326 : 0 : if (!rte_eth_dev_count_avail()) {
327 : 0 : evt_err("No ethernet ports found.");
328 : 0 : return -ENODEV;
329 : : }
330 : :
331 : 0 : if (opt->max_pkt_sz < RTE_ETHER_MIN_LEN) {
332 : 0 : evt_err("max_pkt_sz can not be less than %d",
333 : : RTE_ETHER_MIN_LEN);
334 : 0 : return -EINVAL;
335 : : }
336 : :
337 : 0 : port_conf.rxmode.mtu = opt->max_pkt_sz - RTE_ETHER_HDR_LEN -
338 : : RTE_ETHER_CRC_LEN;
339 : :
340 : 0 : t->internal_port = 1;
341 : 0 : RTE_ETH_FOREACH_DEV(i) {
342 : : struct rte_eth_dev_info dev_info;
343 : 0 : struct rte_eth_conf local_port_conf = port_conf;
344 : 0 : uint32_t caps = 0;
345 : :
346 : 0 : ret = rte_event_eth_tx_adapter_caps_get(opt->dev_id, i, &caps);
347 : 0 : if (ret != 0) {
348 : 0 : evt_err("failed to get event tx adapter[%d] caps", i);
349 : 0 : return ret;
350 : : }
351 : :
352 : 0 : if (!(caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT))
353 : 0 : t->internal_port = 0;
354 : :
355 : 0 : ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id, i, &caps);
356 : 0 : if (ret != 0) {
357 : 0 : evt_err("failed to get event tx adapter[%d] caps", i);
358 : 0 : return ret;
359 : : }
360 : :
361 : 0 : if (!(caps & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT))
362 : 0 : local_port_conf.rxmode.offloads |=
363 : : RTE_ETH_RX_OFFLOAD_RSS_HASH;
364 : :
365 : 0 : ret = rte_eth_dev_info_get(i, &dev_info);
366 : 0 : if (ret != 0) {
367 : 0 : evt_err("Error during getting device (port %u) info: %s\n",
368 : : i, strerror(-ret));
369 : 0 : return ret;
370 : : }
371 : :
372 : : /* Enable mbuf fast free if PMD has the capability. */
373 : 0 : if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
374 : 0 : local_port_conf.txmode.offloads |=
375 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
376 : :
377 : 0 : rx_conf = dev_info.default_rxconf;
378 : 0 : rx_conf.offloads = port_conf.rxmode.offloads;
379 : :
380 : 0 : local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
381 : 0 : dev_info.flow_type_rss_offloads;
382 : 0 : if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
383 : : port_conf.rx_adv_conf.rss_conf.rss_hf) {
384 : 0 : evt_info("Port %u modified RSS hash function based on hardware support,"
385 : : "requested:%#"PRIx64" configured:%#"PRIx64"",
386 : : i,
387 : : port_conf.rx_adv_conf.rss_conf.rss_hf,
388 : : local_port_conf.rx_adv_conf.rss_conf.rss_hf);
389 : : }
390 : :
391 : 0 : if (rte_eth_dev_configure(i, opt->eth_queues, nb_queues,
392 : : &local_port_conf) < 0) {
393 : 0 : evt_err("Failed to configure eth port [%d]", i);
394 : 0 : return -EINVAL;
395 : : }
396 : :
397 : 0 : for (j = 0; j < opt->eth_queues; j++) {
398 : 0 : if (rte_eth_rx_queue_setup(
399 : : i, j, NB_RX_DESC, rte_socket_id(), &rx_conf,
400 : 0 : opt->per_port_pool ? t->pool[i] :
401 : : t->pool[0]) < 0) {
402 : 0 : evt_err("Failed to setup eth port [%d] rx_queue: %d.",
403 : : i, 0);
404 : 0 : return -EINVAL;
405 : : }
406 : : }
407 : :
408 : 0 : if (rte_eth_tx_queue_setup(i, 0, NB_TX_DESC,
409 : : rte_socket_id(), NULL) < 0) {
410 : 0 : evt_err("Failed to setup eth port [%d] tx_queue: %d.",
411 : : i, 0);
412 : 0 : return -EINVAL;
413 : : }
414 : :
415 : 0 : ret = rte_eth_promiscuous_enable(i);
416 : 0 : if (ret != 0) {
417 : 0 : evt_err("Failed to enable promiscuous mode for eth port [%d]: %s",
418 : : i, rte_strerror(-ret));
419 : 0 : return ret;
420 : : }
421 : : }
422 : :
423 : : return 0;
424 : : }
425 : :
426 : : int
427 : 0 : pipeline_event_port_setup(struct evt_test *test, struct evt_options *opt,
428 : : uint8_t *queue_arr, uint8_t nb_queues,
429 : : const struct rte_event_port_conf p_conf)
430 : : {
431 : : int ret;
432 : : uint8_t port;
433 : : struct test_pipeline *t = evt_test_priv(test);
434 : :
435 : :
436 : : /* setup one port per worker, linking to all queues */
437 : 0 : for (port = 0; port < evt_nr_active_lcores(opt->wlcores); port++) {
438 : : struct worker_data *w = &t->worker[port];
439 : :
440 : 0 : w->dev_id = opt->dev_id;
441 : 0 : w->port_id = port;
442 : 0 : w->t = t;
443 : 0 : w->processed_pkts = 0;
444 : :
445 : 0 : ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
446 : 0 : if (ret) {
447 : 0 : evt_err("failed to setup port %d", port);
448 : 0 : return ret;
449 : : }
450 : :
451 : 0 : if (rte_event_port_link(opt->dev_id, port, queue_arr, NULL,
452 : : nb_queues) != nb_queues)
453 : 0 : goto link_fail;
454 : : }
455 : :
456 : : return 0;
457 : :
458 : : link_fail:
459 : 0 : evt_err("failed to link queues to port %d", port);
460 : 0 : return -EINVAL;
461 : : }
462 : :
463 : : int
464 : 0 : pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride,
465 : : struct rte_event_port_conf prod_conf)
466 : : {
467 : : int ret = 0;
468 : : uint16_t prod;
469 : : struct rte_mempool *vector_pool = NULL;
470 : : struct rte_event_eth_rx_adapter_queue_conf queue_conf;
471 : :
472 : : memset(&queue_conf, 0,
473 : : sizeof(struct rte_event_eth_rx_adapter_queue_conf));
474 : 0 : queue_conf.ev.sched_type = opt->sched_type_list[0];
475 : 0 : if (opt->ena_vector) {
476 : 0 : unsigned int nb_elem = (opt->pool_sz / opt->vector_size) << 1;
477 : :
478 : 0 : nb_elem = RTE_MAX(512U, nb_elem);
479 : 0 : nb_elem += evt_nr_active_lcores(opt->wlcores) * 32;
480 : 0 : vector_pool = rte_event_vector_pool_create(
481 : : "vector_pool", nb_elem, 32, opt->vector_size,
482 : : opt->socket_id);
483 : 0 : if (vector_pool == NULL) {
484 : 0 : evt_err("failed to create event vector pool");
485 : 0 : return -ENOMEM;
486 : : }
487 : : }
488 : 0 : RTE_ETH_FOREACH_DEV(prod) {
489 : : struct rte_event_eth_rx_adapter_vector_limits limits;
490 : : uint32_t cap;
491 : :
492 : 0 : ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id,
493 : : prod, &cap);
494 : 0 : if (ret) {
495 : 0 : evt_err("failed to get event rx adapter[%d]"
496 : : " capabilities",
497 : : opt->dev_id);
498 : 0 : return ret;
499 : : }
500 : :
501 : 0 : if (opt->ena_vector) {
502 : : memset(&limits, 0, sizeof(limits));
503 : 0 : ret = rte_event_eth_rx_adapter_vector_limits_get(
504 : 0 : opt->dev_id, prod, &limits);
505 : 0 : if (ret) {
506 : 0 : evt_err("failed to get vector limits");
507 : 0 : return ret;
508 : : }
509 : :
510 : 0 : if (opt->vector_size < limits.min_sz ||
511 : 0 : opt->vector_size > limits.max_sz) {
512 : 0 : evt_err("Vector size [%d] not within limits max[%d] min[%d]",
513 : : opt->vector_size, limits.max_sz,
514 : : limits.min_sz);
515 : 0 : return -EINVAL;
516 : : }
517 : :
518 : 0 : if (limits.log2_sz &&
519 : 0 : !rte_is_power_of_2(opt->vector_size)) {
520 : 0 : evt_err("Vector size [%d] not power of 2",
521 : : opt->vector_size);
522 : 0 : return -EINVAL;
523 : : }
524 : :
525 : 0 : if (opt->vector_tmo_nsec > limits.max_timeout_ns ||
526 : 0 : opt->vector_tmo_nsec < limits.min_timeout_ns) {
527 : 0 : evt_err("Vector timeout [%" PRIu64
528 : : "] not within limits max[%" PRIu64
529 : : "] min[%" PRIu64 "]",
530 : : opt->vector_tmo_nsec,
531 : : limits.max_timeout_ns,
532 : : limits.min_timeout_ns);
533 : 0 : return -EINVAL;
534 : : }
535 : :
536 : 0 : if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_EVENT_VECTOR) {
537 : 0 : queue_conf.vector_sz = opt->vector_size;
538 : 0 : queue_conf.vector_timeout_ns =
539 : : opt->vector_tmo_nsec;
540 : 0 : queue_conf.rx_queue_flags |=
541 : : RTE_EVENT_ETH_RX_ADAPTER_QUEUE_EVENT_VECTOR;
542 : 0 : queue_conf.vector_mp = vector_pool;
543 : : } else {
544 : 0 : evt_err("Rx adapter doesn't support event vector");
545 : 0 : return -EINVAL;
546 : : }
547 : : }
548 : 0 : queue_conf.ev.queue_id = prod * stride;
549 : 0 : ret = rte_event_eth_rx_adapter_create(prod, opt->dev_id,
550 : : &prod_conf);
551 : 0 : if (ret) {
552 : 0 : evt_err("failed to create rx adapter[%d]", prod);
553 : 0 : return ret;
554 : : }
555 : 0 : ret = rte_event_eth_rx_adapter_queue_add(prod, prod, -1,
556 : : &queue_conf);
557 : 0 : if (ret) {
558 : 0 : evt_err("failed to add rx queues to adapter[%d]", prod);
559 : 0 : return ret;
560 : : }
561 : :
562 : 0 : if (!(cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) {
563 : 0 : uint32_t service_id = -1U;
564 : :
565 : 0 : rte_event_eth_rx_adapter_service_id_get(prod,
566 : : &service_id);
567 : 0 : ret = evt_service_setup(service_id);
568 : 0 : if (ret) {
569 : 0 : evt_err("Failed to setup service core"
570 : : " for Rx adapter");
571 : 0 : return ret;
572 : : }
573 : : }
574 : :
575 : 0 : evt_info("Port[%d] using Rx adapter[%d] configured", prod,
576 : : prod);
577 : : }
578 : :
579 : : return ret;
580 : : }
581 : :
582 : : int
583 : 0 : pipeline_event_tx_adapter_setup(struct evt_options *opt,
584 : : struct rte_event_port_conf port_conf)
585 : : {
586 : : int ret = 0;
587 : : uint16_t consm;
588 : :
589 : 0 : RTE_ETH_FOREACH_DEV(consm) {
590 : : uint32_t cap;
591 : :
592 : 0 : ret = rte_event_eth_tx_adapter_caps_get(opt->dev_id,
593 : : consm, &cap);
594 : 0 : if (ret) {
595 : 0 : evt_err("failed to get event tx adapter[%d] caps",
596 : : consm);
597 : 0 : return ret;
598 : : }
599 : :
600 : 0 : if (opt->ena_vector) {
601 : 0 : if (!(cap &
602 : : RTE_EVENT_ETH_TX_ADAPTER_CAP_EVENT_VECTOR)) {
603 : 0 : evt_err("Tx adapter doesn't support event vector");
604 : 0 : return -EINVAL;
605 : : }
606 : : }
607 : :
608 : 0 : ret = rte_event_eth_tx_adapter_create(consm, opt->dev_id,
609 : : &port_conf);
610 : 0 : if (ret) {
611 : 0 : evt_err("failed to create tx adapter[%d]", consm);
612 : 0 : return ret;
613 : : }
614 : :
615 : 0 : ret = rte_event_eth_tx_adapter_queue_add(consm, consm, -1);
616 : 0 : if (ret) {
617 : 0 : evt_err("failed to add tx queues to adapter[%d]",
618 : : consm);
619 : 0 : return ret;
620 : : }
621 : :
622 : 0 : if (!(cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)) {
623 : 0 : uint32_t service_id = -1U;
624 : :
625 : 0 : ret = rte_event_eth_tx_adapter_service_id_get(consm,
626 : : &service_id);
627 : 0 : if (ret != -ESRCH && ret != 0) {
628 : 0 : evt_err("Failed to get Tx adptr service ID");
629 : 0 : return ret;
630 : : }
631 : 0 : ret = evt_service_setup(service_id);
632 : 0 : if (ret) {
633 : 0 : evt_err("Failed to setup service core"
634 : : " for Tx adapter");
635 : 0 : return ret;
636 : : }
637 : : }
638 : :
639 : 0 : evt_info("Port[%d] using Tx adapter[%d] Configured", consm,
640 : : consm);
641 : : }
642 : :
643 : : return ret;
644 : : }
645 : :
646 : : static void
647 : 0 : pipeline_vector_array_free(struct rte_event events[], uint16_t num)
648 : : {
649 : : uint16_t i;
650 : :
651 : 0 : for (i = 0; i < num; i++) {
652 : 0 : rte_pktmbuf_free_bulk(
653 : 0 : &events[i].vec->mbufs[events[i].vec->elem_offset],
654 : 0 : events[i].vec->nb_elem);
655 : 0 : rte_mempool_put(rte_mempool_from_obj(events[i].vec),
656 : 0 : events[i].vec);
657 : : }
658 : 0 : }
659 : :
660 : : static void
661 : 0 : pipeline_event_port_flush(uint8_t dev_id __rte_unused, struct rte_event ev,
662 : : void *args __rte_unused)
663 : : {
664 : 0 : if (ev.event_type & RTE_EVENT_TYPE_VECTOR)
665 : 0 : pipeline_vector_array_free(&ev, 1);
666 : : else
667 : 0 : rte_pktmbuf_free(ev.mbuf);
668 : 0 : }
669 : :
670 : : void
671 : 0 : pipeline_worker_cleanup(uint8_t dev, uint8_t port, struct rte_event ev[],
672 : : uint16_t enq, uint16_t deq)
673 : : {
674 : : int i;
675 : :
676 : 0 : if (deq) {
677 : 0 : for (i = enq; i < deq; i++) {
678 : 0 : if (ev[i].op == RTE_EVENT_OP_RELEASE)
679 : 0 : continue;
680 : 0 : if (ev[i].event_type & RTE_EVENT_TYPE_VECTOR)
681 : 0 : pipeline_vector_array_free(&ev[i], 1);
682 : : else
683 : 0 : rte_pktmbuf_free(ev[i].mbuf);
684 : : }
685 : :
686 : 0 : for (i = enq; i < deq; i++)
687 : 0 : ev[i].op = RTE_EVENT_OP_RELEASE;
688 : :
689 : 0 : rte_event_enqueue_burst(dev, port, ev + enq, deq - enq);
690 : : }
691 : :
692 : 0 : rte_event_port_quiesce(dev, port, pipeline_event_port_flush, NULL);
693 : 0 : }
694 : :
695 : : void
696 : 0 : pipeline_ethdev_rx_stop(struct evt_test *test, struct evt_options *opt)
697 : : {
698 : : uint16_t i, j;
699 : : RTE_SET_USED(test);
700 : :
701 : 0 : if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
702 : 0 : RTE_ETH_FOREACH_DEV(i) {
703 : 0 : rte_event_eth_rx_adapter_stop(i);
704 : 0 : rte_event_eth_rx_adapter_queue_del(i, i, -1);
705 : 0 : for (j = 0; j < opt->eth_queues; j++)
706 : 0 : rte_eth_dev_rx_queue_stop(i, j);
707 : : }
708 : : }
709 : 0 : }
710 : :
711 : : void
712 : 0 : pipeline_ethdev_destroy(struct evt_test *test, struct evt_options *opt)
713 : : {
714 : : uint16_t i;
715 : : RTE_SET_USED(test);
716 : : RTE_SET_USED(opt);
717 : :
718 : 0 : RTE_ETH_FOREACH_DEV(i) {
719 : 0 : rte_event_eth_tx_adapter_stop(i);
720 : 0 : rte_event_eth_tx_adapter_queue_del(i, i, -1);
721 : 0 : rte_eth_dev_tx_queue_stop(i, 0);
722 : 0 : rte_eth_dev_stop(i);
723 : : }
724 : 0 : }
725 : :
726 : : void
727 : 0 : pipeline_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
728 : : {
729 : : RTE_SET_USED(test);
730 : :
731 : 0 : rte_event_dev_stop(opt->dev_id);
732 : 0 : rte_event_dev_close(opt->dev_id);
733 : 0 : }
734 : :
735 : : int
736 : 0 : pipeline_mempool_setup(struct evt_test *test, struct evt_options *opt)
737 : : {
738 : : struct test_pipeline *t = evt_test_priv(test);
739 : : int i, ret;
740 : :
741 : 0 : if (!opt->mbuf_sz)
742 : 0 : opt->mbuf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
743 : :
744 : 0 : if (!opt->max_pkt_sz)
745 : 0 : opt->max_pkt_sz = RTE_ETHER_MAX_LEN;
746 : :
747 : 0 : RTE_ETH_FOREACH_DEV(i) {
748 : : struct rte_eth_dev_info dev_info;
749 : : uint16_t data_size = 0;
750 : :
751 : : memset(&dev_info, 0, sizeof(dev_info));
752 : 0 : ret = rte_eth_dev_info_get(i, &dev_info);
753 : 0 : if (ret != 0) {
754 : 0 : evt_err("Error during getting device (port %u) info: %s\n",
755 : : i, strerror(-ret));
756 : 0 : return ret;
757 : : }
758 : :
759 : 0 : if (dev_info.rx_desc_lim.nb_mtu_seg_max != UINT16_MAX &&
760 : : dev_info.rx_desc_lim.nb_mtu_seg_max != 0) {
761 : 0 : data_size = opt->max_pkt_sz /
762 : 0 : dev_info.rx_desc_lim.nb_mtu_seg_max;
763 : 0 : data_size += RTE_PKTMBUF_HEADROOM;
764 : :
765 : 0 : if (data_size > opt->mbuf_sz)
766 : 0 : opt->mbuf_sz = data_size;
767 : : }
768 : 0 : if (opt->per_port_pool) {
769 : : char name[RTE_MEMPOOL_NAMESIZE];
770 : :
771 : 0 : snprintf(name, RTE_MEMPOOL_NAMESIZE, "%s-%d",
772 : : test->name, i);
773 : 0 : t->pool[i] = rte_pktmbuf_pool_create(
774 : : name, /* mempool name */
775 : 0 : opt->pool_sz, /* number of elements*/
776 : : 0, /* cache size*/
777 : 0 : 0, opt->mbuf_sz, opt->socket_id); /* flags */
778 : :
779 : 0 : if (t->pool[i] == NULL) {
780 : 0 : evt_err("failed to create mempool %s", name);
781 : 0 : return -ENOMEM;
782 : : }
783 : : }
784 : : }
785 : :
786 : 0 : if (!opt->per_port_pool) {
787 : 0 : t->pool[0] = rte_pktmbuf_pool_create(
788 : : test->name, /* mempool name */
789 : 0 : opt->pool_sz, /* number of elements*/
790 : : 0, /* cache size*/
791 : 0 : 0, opt->mbuf_sz, opt->socket_id); /* flags */
792 : :
793 : 0 : if (t->pool[0] == NULL) {
794 : 0 : evt_err("failed to create mempool");
795 : 0 : return -ENOMEM;
796 : : }
797 : : }
798 : :
799 : : return 0;
800 : : }
801 : :
802 : : void
803 : 0 : pipeline_mempool_destroy(struct evt_test *test, struct evt_options *opt)
804 : : {
805 : : struct test_pipeline *t = evt_test_priv(test);
806 : : int i;
807 : :
808 : : RTE_SET_USED(opt);
809 : 0 : if (opt->per_port_pool) {
810 : 0 : RTE_ETH_FOREACH_DEV(i)
811 : 0 : rte_mempool_free(t->pool[i]);
812 : : } else {
813 : 0 : rte_mempool_free(t->pool[0]);
814 : : }
815 : 0 : }
816 : :
817 : : int
818 : 0 : pipeline_test_setup(struct evt_test *test, struct evt_options *opt)
819 : : {
820 : : void *test_pipeline;
821 : :
822 : 0 : test_pipeline = rte_zmalloc_socket(test->name,
823 : : sizeof(struct test_pipeline), RTE_CACHE_LINE_SIZE,
824 : : opt->socket_id);
825 : 0 : if (test_pipeline == NULL) {
826 : 0 : evt_err("failed to allocate test_pipeline memory");
827 : 0 : goto nomem;
828 : : }
829 : 0 : test->test_priv = test_pipeline;
830 : :
831 : : struct test_pipeline *t = evt_test_priv(test);
832 : :
833 : 0 : t->nb_workers = evt_nr_active_lcores(opt->wlcores);
834 : 0 : t->outstand_pkts = opt->nb_pkts * evt_nr_active_lcores(opt->wlcores);
835 : 0 : t->done = false;
836 : 0 : t->nb_flows = opt->nb_flows;
837 : 0 : t->result = EVT_TEST_FAILED;
838 : 0 : t->opt = opt;
839 : 0 : opt->prod_type = EVT_PROD_TYPE_ETH_RX_ADPTR;
840 : 0 : memcpy(t->sched_type_list, opt->sched_type_list,
841 : : sizeof(opt->sched_type_list));
842 : 0 : return 0;
843 : : nomem:
844 : 0 : return -ENOMEM;
845 : : }
846 : :
847 : : void
848 : 0 : pipeline_test_destroy(struct evt_test *test, struct evt_options *opt)
849 : : {
850 : : RTE_SET_USED(opt);
851 : :
852 : 0 : rte_free(test->test_priv);
853 : 0 : }
|