]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/app/test-pmd/softnicfwd.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / app / test-pmd / softnicfwd.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
3 */
4#include <stdio.h>
5#include <sys/stat.h>
6
7#include <rte_cycles.h>
8#include <rte_mbuf.h>
9#include <rte_malloc.h>
10#include <rte_ethdev.h>
11#include <rte_flow.h>
12#include <rte_meter.h>
13#include <rte_eth_softnic.h>
14#include <rte_tm.h>
15
16#include "testpmd.h"
17
18#define SUBPORT_NODES_PER_PORT 1
19#define PIPE_NODES_PER_SUBPORT 4096
20#define TC_NODES_PER_PIPE 4
21#define QUEUE_NODES_PER_TC 4
22
23#define NUM_PIPE_NODES \
24 (SUBPORT_NODES_PER_PORT * PIPE_NODES_PER_SUBPORT)
25
26#define NUM_TC_NODES \
27 (NUM_PIPE_NODES * TC_NODES_PER_PIPE)
28
29#define ROOT_NODE_ID 1000000
30#define SUBPORT_NODES_START_ID 900000
31#define PIPE_NODES_START_ID 800000
32#define TC_NODES_START_ID 700000
33
34#define STATS_MASK_DEFAULT \
35 (RTE_TM_STATS_N_PKTS | \
36 RTE_TM_STATS_N_BYTES | \
37 RTE_TM_STATS_N_PKTS_GREEN_DROPPED | \
38 RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
39
40#define STATS_MASK_QUEUE \
41 (STATS_MASK_DEFAULT | \
42 RTE_TM_STATS_N_PKTS_QUEUED)
43
44#define BYTES_IN_MBPS (1000 * 1000 / 8)
45#define TOKEN_BUCKET_SIZE 1000000
46
47/* TM Hierarchy Levels */
48enum tm_hierarchy_level {
49 TM_NODE_LEVEL_PORT = 0,
50 TM_NODE_LEVEL_SUBPORT,
51 TM_NODE_LEVEL_PIPE,
52 TM_NODE_LEVEL_TC,
53 TM_NODE_LEVEL_QUEUE,
54 TM_NODE_LEVEL_MAX,
55};
56
57struct tm_hierarchy {
58 /* TM Nodes */
59 uint32_t root_node_id;
60 uint32_t subport_node_id[SUBPORT_NODES_PER_PORT];
61 uint32_t pipe_node_id[SUBPORT_NODES_PER_PORT][PIPE_NODES_PER_SUBPORT];
62 uint32_t tc_node_id[NUM_PIPE_NODES][TC_NODES_PER_PIPE];
63 uint32_t queue_node_id[NUM_TC_NODES][QUEUE_NODES_PER_TC];
64
65 /* TM Hierarchy Nodes Shaper Rates */
66 uint32_t root_node_shaper_rate;
67 uint32_t subport_node_shaper_rate;
68 uint32_t pipe_node_shaper_rate;
69 uint32_t tc_node_shaper_rate;
70 uint32_t tc_node_shared_shaper_rate;
71
72 uint32_t n_shapers;
73};
74
75static struct fwd_lcore *softnic_fwd_lcore;
76static uint16_t softnic_port_id;
77struct fwd_engine softnic_fwd_engine;
78
79/*
80 * Softnic packet forward
81 */
82static void
83softnic_fwd(struct fwd_stream *fs)
84{
85 struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
86 uint16_t nb_rx;
87 uint16_t nb_tx;
88 uint32_t retry;
89
90#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
91 uint64_t start_tsc;
92 uint64_t end_tsc;
93 uint64_t core_cycles;
94#endif
95
96#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
97 start_tsc = rte_rdtsc();
98#endif
99
100 /* Packets Receive */
101 nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
102 pkts_burst, nb_pkt_per_burst);
103 fs->rx_packets += nb_rx;
104
105#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
106 fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
107#endif
108
109 nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
110 pkts_burst, nb_rx);
111
112 /* Retry if necessary */
113 if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
114 retry = 0;
115 while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
116 rte_delay_us(burst_tx_delay_time);
117 nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
118 &pkts_burst[nb_tx], nb_rx - nb_tx);
119 }
120 }
121 fs->tx_packets += nb_tx;
122
123#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
124 fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
125#endif
126
127 if (unlikely(nb_tx < nb_rx)) {
128 fs->fwd_dropped += (nb_rx - nb_tx);
129 do {
130 rte_pktmbuf_free(pkts_burst[nb_tx]);
131 } while (++nb_tx < nb_rx);
132 }
133#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
134 end_tsc = rte_rdtsc();
135 core_cycles = (end_tsc - start_tsc);
136 fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
137#endif
138}
139
140static void
141softnic_fwd_run(struct fwd_stream *fs)
142{
143 rte_pmd_softnic_run(softnic_port_id);
144 softnic_fwd(fs);
145}
146
147/**
148 * Softnic init
149 */
150static int
151softnic_begin(void *arg __rte_unused)
152{
153 for (;;) {
154 if (!softnic_fwd_lcore->stopped)
155 break;
156 }
157
158 do {
159 /* Run softnic */
160 rte_pmd_softnic_run(softnic_port_id);
161 } while (!softnic_fwd_lcore->stopped);
162
163 return 0;
164}
165
f67539c2 166static int
11fdf7f2
TL
167set_tm_hiearchy_nodes_shaper_rate(portid_t port_id,
168 struct tm_hierarchy *h)
169{
170 struct rte_eth_link link_params;
171 uint64_t tm_port_rate;
f67539c2 172 int ret;
11fdf7f2
TL
173
174 memset(&link_params, 0, sizeof(link_params));
175
f67539c2
TL
176 ret = rte_eth_link_get(port_id, &link_params);
177 if (ret < 0) {
178 printf("Error during getting device (port %u) link info: %s\n",
179 port_id, rte_strerror(-ret));
180 return ret;
181 }
11fdf7f2
TL
182 tm_port_rate = (uint64_t)ETH_SPEED_NUM_10G * BYTES_IN_MBPS;
183
184 /* Set tm hierarchy shapers rate */
185 h->root_node_shaper_rate = tm_port_rate;
186 h->subport_node_shaper_rate =
187 tm_port_rate / SUBPORT_NODES_PER_PORT;
188 h->pipe_node_shaper_rate
189 = h->subport_node_shaper_rate / PIPE_NODES_PER_SUBPORT;
190 h->tc_node_shaper_rate = h->pipe_node_shaper_rate;
191 h->tc_node_shared_shaper_rate = h->subport_node_shaper_rate;
f67539c2
TL
192
193 return 0;
11fdf7f2
TL
194}
195
196static int
197softport_tm_root_node_add(portid_t port_id, struct tm_hierarchy *h,
198 struct rte_tm_error *error)
199{
200 struct rte_tm_node_params rnp;
201 struct rte_tm_shaper_params rsp;
202 uint32_t priority, weight, level_id, shaper_profile_id;
203
204 memset(&rsp, 0, sizeof(struct rte_tm_shaper_params));
205 memset(&rnp, 0, sizeof(struct rte_tm_node_params));
206
207 /* Shaper profile Parameters */
208 rsp.peak.rate = h->root_node_shaper_rate;
209 rsp.peak.size = TOKEN_BUCKET_SIZE;
210 rsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
211 shaper_profile_id = 0;
212
213 if (rte_tm_shaper_profile_add(port_id, shaper_profile_id,
214 &rsp, error)) {
215 printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
216 __func__, error->type, error->message,
217 shaper_profile_id);
218 return -1;
219 }
220
221 /* Root Node Parameters */
222 h->root_node_id = ROOT_NODE_ID;
223 weight = 1;
224 priority = 0;
225 level_id = TM_NODE_LEVEL_PORT;
226 rnp.shaper_profile_id = shaper_profile_id;
227 rnp.nonleaf.n_sp_priorities = 1;
228 rnp.stats_mask = STATS_MASK_DEFAULT;
229
230 /* Add Node to TM Hierarchy */
231 if (rte_tm_node_add(port_id, h->root_node_id, RTE_TM_NODE_ID_NULL,
232 priority, weight, level_id, &rnp, error)) {
233 printf("%s ERROR(%d)-%s!(node_id %u, parent_id %u, level %u)\n",
234 __func__, error->type, error->message,
235 h->root_node_id, RTE_TM_NODE_ID_NULL,
236 level_id);
237 return -1;
238 }
239 /* Update */
240 h->n_shapers++;
241
242 printf(" Root node added (Start id %u, Count %u, level %u)\n",
243 h->root_node_id, 1, level_id);
244
245 return 0;
246}
247
248static int
249softport_tm_subport_node_add(portid_t port_id,
250 struct tm_hierarchy *h,
251 struct rte_tm_error *error)
252{
253 uint32_t subport_parent_node_id, subport_node_id = 0;
254 struct rte_tm_node_params snp;
255 struct rte_tm_shaper_params ssp;
256 uint32_t priority, weight, level_id, shaper_profile_id;
257 uint32_t i;
258
259 memset(&ssp, 0, sizeof(struct rte_tm_shaper_params));
260 memset(&snp, 0, sizeof(struct rte_tm_node_params));
261
262 shaper_profile_id = h->n_shapers;
263
264 /* Add Shaper Profile to TM Hierarchy */
265 for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
266 ssp.peak.rate = h->subport_node_shaper_rate;
267 ssp.peak.size = TOKEN_BUCKET_SIZE;
268 ssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
269
270 if (rte_tm_shaper_profile_add(port_id, shaper_profile_id,
271 &ssp, error)) {
272 printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
273 __func__, error->type, error->message,
274 shaper_profile_id);
275 return -1;
276 }
277
278 /* Node Parameters */
279 h->subport_node_id[i] = SUBPORT_NODES_START_ID + i;
280 subport_parent_node_id = h->root_node_id;
281 weight = 1;
282 priority = 0;
283 level_id = TM_NODE_LEVEL_SUBPORT;
284 snp.shaper_profile_id = shaper_profile_id;
285 snp.nonleaf.n_sp_priorities = 1;
286 snp.stats_mask = STATS_MASK_DEFAULT;
287
288 /* Add Node to TM Hiearchy */
289 if (rte_tm_node_add(port_id,
290 h->subport_node_id[i],
291 subport_parent_node_id,
292 priority, weight,
293 level_id,
294 &snp,
295 error)) {
296 printf("%s ERROR(%d)-%s!(node %u,parent %u,level %u)\n",
297 __func__,
298 error->type,
299 error->message,
300 h->subport_node_id[i],
301 subport_parent_node_id,
302 level_id);
303 return -1;
304 }
305 shaper_profile_id++;
306 subport_node_id++;
307 }
308 /* Update */
309 h->n_shapers = shaper_profile_id;
310
311 printf(" Subport nodes added (Start id %u, Count %u, level %u)\n",
312 h->subport_node_id[0], SUBPORT_NODES_PER_PORT, level_id);
313
314 return 0;
315}
316
317static int
318softport_tm_pipe_node_add(portid_t port_id,
319 struct tm_hierarchy *h,
320 struct rte_tm_error *error)
321{
322 uint32_t pipe_parent_node_id;
323 struct rte_tm_node_params pnp;
324 struct rte_tm_shaper_params psp;
325 uint32_t priority, weight, level_id, shaper_profile_id;
326 uint32_t i, j;
327
328 memset(&psp, 0, sizeof(struct rte_tm_shaper_params));
329 memset(&pnp, 0, sizeof(struct rte_tm_node_params));
330
331 shaper_profile_id = h->n_shapers;
332
333 /* Shaper Profile Parameters */
334 psp.peak.rate = h->pipe_node_shaper_rate;
335 psp.peak.size = TOKEN_BUCKET_SIZE;
336 psp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
337
338 /* Pipe Node Parameters */
339 weight = 1;
340 priority = 0;
341 level_id = TM_NODE_LEVEL_PIPE;
342 pnp.nonleaf.n_sp_priorities = 4;
343 pnp.stats_mask = STATS_MASK_DEFAULT;
344
345 /* Add Shaper Profiles and Nodes to TM Hierarchy */
346 for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
347 for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {
348 if (rte_tm_shaper_profile_add(port_id,
349 shaper_profile_id, &psp, error)) {
350 printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
351 __func__, error->type, error->message,
352 shaper_profile_id);
353 return -1;
354 }
355 pnp.shaper_profile_id = shaper_profile_id;
356 pipe_parent_node_id = h->subport_node_id[i];
357 h->pipe_node_id[i][j] = PIPE_NODES_START_ID +
358 (i * PIPE_NODES_PER_SUBPORT) + j;
359
360 if (rte_tm_node_add(port_id,
361 h->pipe_node_id[i][j],
362 pipe_parent_node_id,
363 priority, weight, level_id,
364 &pnp,
365 error)) {
366 printf("%s ERROR(%d)-%s!(node %u,parent %u )\n",
367 __func__,
368 error->type,
369 error->message,
370 h->pipe_node_id[i][j],
371 pipe_parent_node_id);
372
373 return -1;
374 }
375 shaper_profile_id++;
376 }
377 }
378 /* Update */
379 h->n_shapers = shaper_profile_id;
380
381 printf(" Pipe nodes added (Start id %u, Count %u, level %u)\n",
382 h->pipe_node_id[0][0], NUM_PIPE_NODES, level_id);
383
384 return 0;
385}
386
387static int
388softport_tm_tc_node_add(portid_t port_id,
389 struct tm_hierarchy *h,
390 struct rte_tm_error *error)
391{
392 uint32_t tc_parent_node_id;
393 struct rte_tm_node_params tnp;
394 struct rte_tm_shaper_params tsp, tssp;
395 uint32_t shared_shaper_profile_id[TC_NODES_PER_PIPE];
396 uint32_t priority, weight, level_id, shaper_profile_id;
397 uint32_t pos, n_tc_nodes, i, j, k;
398
399 memset(&tsp, 0, sizeof(struct rte_tm_shaper_params));
400 memset(&tssp, 0, sizeof(struct rte_tm_shaper_params));
401 memset(&tnp, 0, sizeof(struct rte_tm_node_params));
402
403 shaper_profile_id = h->n_shapers;
404
405 /* Private Shaper Profile (TC) Parameters */
406 tsp.peak.rate = h->tc_node_shaper_rate;
407 tsp.peak.size = TOKEN_BUCKET_SIZE;
408 tsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
409
410 /* Shared Shaper Profile (TC) Parameters */
411 tssp.peak.rate = h->tc_node_shared_shaper_rate;
412 tssp.peak.size = TOKEN_BUCKET_SIZE;
413 tssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
414
415 /* TC Node Parameters */
416 weight = 1;
417 level_id = TM_NODE_LEVEL_TC;
418 tnp.n_shared_shapers = 1;
419 tnp.nonleaf.n_sp_priorities = 1;
420 tnp.stats_mask = STATS_MASK_DEFAULT;
421
422 /* Add Shared Shaper Profiles to TM Hierarchy */
423 for (i = 0; i < TC_NODES_PER_PIPE; i++) {
424 shared_shaper_profile_id[i] = shaper_profile_id;
425
426 if (rte_tm_shaper_profile_add(port_id,
427 shared_shaper_profile_id[i], &tssp, error)) {
428 printf("%s ERROR(%d)-%s!(Shared shaper profileid %u)\n",
429 __func__, error->type, error->message,
430 shared_shaper_profile_id[i]);
431
432 return -1;
433 }
434 if (rte_tm_shared_shaper_add_update(port_id, i,
435 shared_shaper_profile_id[i], error)) {
436 printf("%s ERROR(%d)-%s!(Shared shaper id %u)\n",
437 __func__, error->type, error->message, i);
438
439 return -1;
440 }
441 shaper_profile_id++;
442 }
443
444 /* Add Shaper Profiles and Nodes to TM Hierarchy */
445 n_tc_nodes = 0;
446 for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
447 for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {
448 for (k = 0; k < TC_NODES_PER_PIPE ; k++) {
449 priority = k;
450 tc_parent_node_id = h->pipe_node_id[i][j];
451 tnp.shared_shaper_id =
452 (uint32_t *)calloc(1, sizeof(uint32_t));
453 if (tnp.shared_shaper_id == NULL) {
454 printf("Shared shaper mem alloc err\n");
455 return -1;
456 }
457 tnp.shared_shaper_id[0] = k;
458 pos = j + (i * PIPE_NODES_PER_SUBPORT);
459 h->tc_node_id[pos][k] =
460 TC_NODES_START_ID + n_tc_nodes;
461
462 if (rte_tm_shaper_profile_add(port_id,
463 shaper_profile_id, &tsp, error)) {
464 printf("%s ERROR(%d)-%s!(shaper %u)\n",
465 __func__, error->type,
466 error->message,
467 shaper_profile_id);
468
9f95a23c 469 free(tnp.shared_shaper_id);
11fdf7f2
TL
470 return -1;
471 }
472 tnp.shaper_profile_id = shaper_profile_id;
473 if (rte_tm_node_add(port_id,
474 h->tc_node_id[pos][k],
475 tc_parent_node_id,
476 priority, weight,
477 level_id,
478 &tnp, error)) {
479 printf("%s ERROR(%d)-%s!(node id %u)\n",
480 __func__,
481 error->type,
482 error->message,
483 h->tc_node_id[pos][k]);
484
9f95a23c 485 free(tnp.shared_shaper_id);
11fdf7f2
TL
486 return -1;
487 }
488 shaper_profile_id++;
489 n_tc_nodes++;
490 }
491 }
492 }
493 /* Update */
494 h->n_shapers = shaper_profile_id;
495
496 printf(" TC nodes added (Start id %u, Count %u, level %u)\n",
497 h->tc_node_id[0][0], n_tc_nodes, level_id);
498
499 return 0;
500}
501
502static int
503softport_tm_queue_node_add(portid_t port_id, struct tm_hierarchy *h,
504 struct rte_tm_error *error)
505{
506 uint32_t queue_parent_node_id;
507 struct rte_tm_node_params qnp;
508 uint32_t priority, weight, level_id, pos;
509 uint32_t n_queue_nodes, i, j, k;
510
511 memset(&qnp, 0, sizeof(struct rte_tm_node_params));
512
513 /* Queue Node Parameters */
514 priority = 0;
515 weight = 1;
516 level_id = TM_NODE_LEVEL_QUEUE;
517 qnp.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
518 qnp.leaf.cman = RTE_TM_CMAN_TAIL_DROP;
519 qnp.stats_mask = STATS_MASK_QUEUE;
520
521 /* Add Queue Nodes to TM Hierarchy */
522 n_queue_nodes = 0;
523 for (i = 0; i < NUM_PIPE_NODES; i++) {
524 for (j = 0; j < TC_NODES_PER_PIPE; j++) {
525 queue_parent_node_id = h->tc_node_id[i][j];
526 for (k = 0; k < QUEUE_NODES_PER_TC; k++) {
527 pos = j + (i * TC_NODES_PER_PIPE);
528 h->queue_node_id[pos][k] = n_queue_nodes;
529 if (rte_tm_node_add(port_id,
530 h->queue_node_id[pos][k],
531 queue_parent_node_id,
532 priority,
533 weight,
534 level_id,
535 &qnp, error)) {
536 printf("%s ERROR(%d)-%s!(node %u)\n",
537 __func__,
538 error->type,
539 error->message,
540 h->queue_node_id[pos][k]);
541
542 return -1;
543 }
544 n_queue_nodes++;
545 }
546 }
547 }
548 printf(" Queue nodes added (Start id %u, Count %u, level %u)\n",
549 h->queue_node_id[0][0], n_queue_nodes, level_id);
550
551 return 0;
552}
553
554static int
555softport_tm_hierarchy_specify(portid_t port_id,
556 struct rte_tm_error *error)
557{
558
559 struct tm_hierarchy h;
560 int status;
561
562 memset(&h, 0, sizeof(struct tm_hierarchy));
563
564 /* TM hierarchy shapers rate */
f67539c2
TL
565 status = set_tm_hiearchy_nodes_shaper_rate(port_id, &h);
566 if (status)
567 return status;
11fdf7f2
TL
568
569 /* Add root node (level 0) */
570 status = softport_tm_root_node_add(port_id, &h, error);
571 if (status)
572 return status;
573
574 /* Add subport node (level 1) */
575 status = softport_tm_subport_node_add(port_id, &h, error);
576 if (status)
577 return status;
578
579 /* Add pipe nodes (level 2) */
580 status = softport_tm_pipe_node_add(port_id, &h, error);
581 if (status)
582 return status;
583
584 /* Add traffic class nodes (level 3) */
585 status = softport_tm_tc_node_add(port_id, &h, error);
586 if (status)
587 return status;
588
589 /* Add queue nodes (level 4) */
590 status = softport_tm_queue_node_add(port_id, &h, error);
591 if (status)
592 return status;
593
594 return 0;
595}
596
597/*
598 * Softnic TM default configuration
599 */
600static void
601softnic_tm_default_config(portid_t pi)
602{
603 struct rte_port *port = &ports[pi];
604 struct rte_tm_error error;
605 int status;
606
607 /* Stop port */
608 rte_eth_dev_stop(pi);
609
610 /* TM hierarchy specification */
611 status = softport_tm_hierarchy_specify(pi, &error);
612 if (status) {
613 printf(" TM Hierarchy built error(%d) - %s\n",
614 error.type, error.message);
615 return;
616 }
617 printf("\n TM Hierarchy Specified!\n");
618
619 /* TM hierarchy commit */
620 status = rte_tm_hierarchy_commit(pi, 0, &error);
621 if (status) {
622 printf(" Hierarchy commit error(%d) - %s\n",
623 error.type, error.message);
624 return;
625 }
626 printf(" Hierarchy Committed (port %u)!\n", pi);
627
628 /* Start port */
629 status = rte_eth_dev_start(pi);
630 if (status) {
631 printf("\n Port %u start error!\n", pi);
632 return;
633 }
634
635 /* Reset the default hierarchy flag */
636 port->softport.default_tm_hierarchy_enable = 0;
637}
638
639/*
640 * Softnic forwarding init
641 */
642static void
643softnic_fwd_begin(portid_t pi)
644{
645 struct rte_port *port = &ports[pi];
646 uint32_t lcore, fwd_core_present = 0, softnic_run_launch = 0;
647 int status;
648
649 softnic_fwd_lcore = port->softport.fwd_lcore_arg[0];
650 softnic_port_id = pi;
651
652 /* Launch softnic_run function on lcores */
653 for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) {
654 if (!rte_lcore_is_enabled(lcore))
655 continue;
656
657 if (lcore == rte_get_master_lcore())
658 continue;
659
660 if (fwd_core_present == 0) {
661 fwd_core_present++;
662 continue;
663 }
664
665 status = rte_eal_remote_launch(softnic_begin, NULL, lcore);
666 if (status)
667 printf("softnic launch on lcore %u failed (%d)\n",
668 lcore, status);
669
670 softnic_run_launch = 1;
671 }
672
673 if (!softnic_run_launch)
674 softnic_fwd_engine.packet_fwd = softnic_fwd_run;
675
676 /* Softnic TM default configuration */
677 if (port->softport.default_tm_hierarchy_enable == 1)
678 softnic_tm_default_config(pi);
679}
680
681struct fwd_engine softnic_fwd_engine = {
682 .fwd_mode_name = "softnic",
683 .port_fwd_begin = softnic_fwd_begin,
684 .port_fwd_end = NULL,
685 .packet_fwd = softnic_fwd,
686};