1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
11 #include <sys/queue.h>
16 #include <rte_common.h>
17 #include <rte_byteorder.h>
19 #include <rte_memory.h>
20 #include <rte_memcpy.h>
22 #include <rte_launch.h>
23 #include <rte_atomic.h>
24 #include <rte_cycles.h>
25 #include <rte_prefetch.h>
26 #include <rte_lcore.h>
27 #include <rte_per_lcore.h>
28 #include <rte_branch_prediction.h>
29 #include <rte_interrupts.h>
30 #include <rte_random.h>
31 #include <rte_debug.h>
32 #include <rte_ether.h>
33 #include <rte_ethdev.h>
34 #include <rte_mempool.h>
39 #include <rte_string_fns.h>
43 struct app_params app
;
45 static const char usage
[] =
47 " load_balancer <EAL PARAMS> -- <APP PARAMS> \n"
49 "Application manadatory parameters: \n"
50 " --rx \"(PORT, QUEUE, LCORE), ...\" : List of NIC RX ports and queues \n"
51 " handled by the I/O RX lcores \n"
52 " --tx \"(PORT, LCORE), ...\" : List of NIC TX ports handled by the I/O TX \n"
54 " --w \"LCORE, ...\" : List of the worker lcores \n"
55 " --lpm \"IP / PREFIX => PORT; ...\" : List of LPM rules used by the worker \n"
56 " lcores for packet forwarding \n"
58 "Application optional parameters: \n"
59 " --rsz \"A, B, C, D\" : Ring sizes \n"
60 " A = Size (in number of buffer descriptors) of each of the NIC RX \n"
61 " rings read by the I/O RX lcores (default value is %u) \n"
62 " B = Size (in number of elements) of each of the SW rings used by the\n"
63 " I/O RX lcores to send packets to worker lcores (default value is\n"
65 " C = Size (in number of elements) of each of the SW rings used by the\n"
66 " worker lcores to send packets to I/O TX lcores (default value is\n"
68 " D = Size (in number of buffer descriptors) of each of the NIC TX \n"
69 " rings written by I/O TX lcores (default value is %u) \n"
70 " --bsz \"(A, B), (C, D), (E, F)\" : Burst sizes \n"
71 " A = I/O RX lcore read burst size from NIC RX (default value is %u) \n"
72 " B = I/O RX lcore write burst size to output SW rings (default value \n"
74 " C = Worker lcore read burst size from input SW rings (default value \n"
76 " D = Worker lcore write burst size to output SW rings (default value \n"
78 " E = I/O TX lcore read burst size from input SW rings (default value \n"
80 " F = I/O TX lcore write burst size to NIC TX (default value is %u) \n"
81 " --pos-lb POS : Position of the 1-byte field within the input packet used by\n"
82 " the I/O RX lcores to identify the worker lcore for the current \n"
83 " packet (default value is %u) \n";
89 APP_DEFAULT_NIC_RX_RING_SIZE
,
90 APP_DEFAULT_RING_RX_SIZE
,
91 APP_DEFAULT_RING_TX_SIZE
,
92 APP_DEFAULT_NIC_TX_RING_SIZE
,
93 APP_DEFAULT_BURST_SIZE_IO_RX_READ
,
94 APP_DEFAULT_BURST_SIZE_IO_RX_WRITE
,
95 APP_DEFAULT_BURST_SIZE_WORKER_READ
,
96 APP_DEFAULT_BURST_SIZE_WORKER_WRITE
,
97 APP_DEFAULT_BURST_SIZE_IO_TX_READ
,
98 APP_DEFAULT_BURST_SIZE_IO_TX_WRITE
,
99 APP_DEFAULT_IO_RX_LB_POS
103 #ifndef APP_ARG_RX_MAX_CHARS
104 #define APP_ARG_RX_MAX_CHARS 4096
107 #ifndef APP_ARG_RX_MAX_TUPLES
108 #define APP_ARG_RX_MAX_TUPLES 128
112 str_to_unsigned_array(
113 const char *s
, size_t sbuflen
,
119 char *splits
[num_vals
];
121 int i
, num_splits
= 0;
123 /* copy s so we don't modify original string */
124 strlcpy(str
, s
, sizeof(str
));
125 num_splits
= rte_strsplit(str
, sizeof(str
), splits
, num_vals
, separator
);
128 for (i
= 0; i
< num_splits
; i
++) {
129 vals
[i
] = strtoul(splits
[i
], &endptr
, 0);
130 if (errno
!= 0 || *endptr
!= '\0')
138 str_to_unsigned_vals(
142 unsigned num_vals
, ...)
144 unsigned i
, vals
[num_vals
];
147 num_vals
= str_to_unsigned_array(s
, sbuflen
, separator
, num_vals
, vals
);
149 va_start(ap
, num_vals
);
150 for (i
= 0; i
< num_vals
; i
++) {
151 unsigned *u
= va_arg(ap
, unsigned *);
159 parse_arg_rx(const char *arg
)
161 const char *p0
= arg
, *p
= arg
;
164 if (strnlen(arg
, APP_ARG_RX_MAX_CHARS
+ 1) == APP_ARG_RX_MAX_CHARS
+ 1) {
169 while ((p
= strchr(p0
,'(')) != NULL
) {
170 struct app_lcore_params
*lp
;
171 uint32_t port
, queue
, lcore
, i
;
173 p0
= strchr(p
++, ')');
175 (str_to_unsigned_vals(p
, p0
- p
, ',', 3, &port
, &queue
, &lcore
) != 3)) {
179 /* Enable port and queue for later initialization */
180 if ((port
>= APP_MAX_NIC_PORTS
) || (queue
>= APP_MAX_RX_QUEUES_PER_NIC_PORT
)) {
183 if (app
.nic_rx_queue_mask
[port
][queue
] != 0) {
186 app
.nic_rx_queue_mask
[port
][queue
] = 1;
188 /* Check and assign (port, queue) to I/O lcore */
189 if (rte_lcore_is_enabled(lcore
) == 0) {
193 if (lcore
>= APP_MAX_LCORES
) {
196 lp
= &app
.lcore_params
[lcore
];
197 if (lp
->type
== e_APP_LCORE_WORKER
) {
200 lp
->type
= e_APP_LCORE_IO
;
201 const size_t n_queues
= RTE_MIN(lp
->io
.rx
.n_nic_queues
,
202 RTE_DIM(lp
->io
.rx
.nic_queues
));
203 for (i
= 0; i
< n_queues
; i
++) {
204 if ((lp
->io
.rx
.nic_queues
[i
].port
== port
) &&
205 (lp
->io
.rx
.nic_queues
[i
].queue
== queue
)) {
209 if (lp
->io
.rx
.n_nic_queues
>= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE
) {
212 lp
->io
.rx
.nic_queues
[lp
->io
.rx
.n_nic_queues
].port
= port
;
213 lp
->io
.rx
.nic_queues
[lp
->io
.rx
.n_nic_queues
].queue
= (uint8_t) queue
;
214 lp
->io
.rx
.n_nic_queues
++;
217 if (n_tuples
> APP_ARG_RX_MAX_TUPLES
) {
229 #ifndef APP_ARG_TX_MAX_CHARS
230 #define APP_ARG_TX_MAX_CHARS 4096
233 #ifndef APP_ARG_TX_MAX_TUPLES
234 #define APP_ARG_TX_MAX_TUPLES 128
238 parse_arg_tx(const char *arg
)
240 const char *p0
= arg
, *p
= arg
;
243 if (strnlen(arg
, APP_ARG_TX_MAX_CHARS
+ 1) == APP_ARG_TX_MAX_CHARS
+ 1) {
248 while ((p
= strchr(p0
,'(')) != NULL
) {
249 struct app_lcore_params
*lp
;
250 uint32_t port
, lcore
, i
;
252 p0
= strchr(p
++, ')');
254 (str_to_unsigned_vals(p
, p0
- p
, ',', 2, &port
, &lcore
) != 2)) {
258 /* Enable port and queue for later initialization */
259 if (port
>= APP_MAX_NIC_PORTS
) {
262 if (app
.nic_tx_port_mask
[port
] != 0) {
265 app
.nic_tx_port_mask
[port
] = 1;
267 /* Check and assign (port, queue) to I/O lcore */
268 if (rte_lcore_is_enabled(lcore
) == 0) {
272 if (lcore
>= APP_MAX_LCORES
) {
275 lp
= &app
.lcore_params
[lcore
];
276 if (lp
->type
== e_APP_LCORE_WORKER
) {
279 lp
->type
= e_APP_LCORE_IO
;
280 const size_t n_ports
= RTE_MIN(lp
->io
.tx
.n_nic_ports
,
281 RTE_DIM(lp
->io
.tx
.nic_ports
));
282 for (i
= 0; i
< n_ports
; i
++) {
283 if (lp
->io
.tx
.nic_ports
[i
] == port
) {
287 if (lp
->io
.tx
.n_nic_ports
>= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE
) {
290 lp
->io
.tx
.nic_ports
[lp
->io
.tx
.n_nic_ports
] = port
;
291 lp
->io
.tx
.n_nic_ports
++;
294 if (n_tuples
> APP_ARG_TX_MAX_TUPLES
) {
306 #ifndef APP_ARG_W_MAX_CHARS
307 #define APP_ARG_W_MAX_CHARS 4096
310 #ifndef APP_ARG_W_MAX_TUPLES
311 #define APP_ARG_W_MAX_TUPLES APP_MAX_WORKER_LCORES
315 parse_arg_w(const char *arg
)
320 if (strnlen(arg
, APP_ARG_W_MAX_CHARS
+ 1) == APP_ARG_W_MAX_CHARS
+ 1) {
326 struct app_lcore_params
*lp
;
330 lcore
= strtoul(p
, NULL
, 0);
335 /* Check and enable worker lcore */
336 if (rte_lcore_is_enabled(lcore
) == 0) {
340 if (lcore
>= APP_MAX_LCORES
) {
343 lp
= &app
.lcore_params
[lcore
];
344 if (lp
->type
== e_APP_LCORE_IO
) {
347 lp
->type
= e_APP_LCORE_WORKER
;
350 if (n_tuples
> APP_ARG_W_MAX_TUPLES
) {
365 if ((n_tuples
& (n_tuples
- 1)) != 0) {
372 #ifndef APP_ARG_LPM_MAX_CHARS
373 #define APP_ARG_LPM_MAX_CHARS 4096
377 parse_arg_lpm(const char *arg
)
379 const char *p
= arg
, *p0
;
381 if (strnlen(arg
, APP_ARG_LPM_MAX_CHARS
+ 1) == APP_ARG_TX_MAX_CHARS
+ 1) {
386 uint32_t ip_a
, ip_b
, ip_c
, ip_d
, ip
, depth
, if_out
;
391 (str_to_unsigned_vals(p
, p0
- p
, '.', 4, &ip_a
, &ip_b
, &ip_c
, &ip_d
) != 4)) {
397 depth
= strtoul(p
, &endptr
, 0);
398 if (errno
!= 0 || *endptr
!= '=') {
405 if_out
= strtoul(++p
, &endptr
, 0);
406 if (errno
!= 0 || (*endptr
!= '\0' && *endptr
!= ';')) {
410 if ((ip_a
>= 256) || (ip_b
>= 256) || (ip_c
>= 256) || (ip_d
>= 256) ||
411 (depth
== 0) || (depth
>= 32) ||
412 (if_out
>= APP_MAX_NIC_PORTS
)) {
415 ip
= (ip_a
<< 24) | (ip_b
<< 16) | (ip_c
<< 8) | ip_d
;
417 if (app
.n_lpm_rules
>= APP_MAX_LPM_RULES
) {
420 app
.lpm_rules
[app
.n_lpm_rules
].ip
= ip
;
421 app
.lpm_rules
[app
.n_lpm_rules
].depth
= (uint8_t) depth
;
422 app
.lpm_rules
[app
.n_lpm_rules
].if_out
= (uint8_t) if_out
;
432 if (app
.n_lpm_rules
== 0) {
440 app_check_lpm_table(void)
444 /* For each rule, check that the output I/F is enabled */
445 for (rule
= 0; rule
< app
.n_lpm_rules
; rule
++)
447 uint32_t port
= app
.lpm_rules
[rule
].if_out
;
449 if (app
.nic_tx_port_mask
[port
] == 0) {
458 app_check_every_rx_port_is_tx_enabled(void)
462 for (port
= 0; port
< APP_MAX_NIC_PORTS
; port
++) {
463 if ((app_get_nic_rx_queues_per_port(port
) > 0) && (app
.nic_tx_port_mask
[port
] == 0)) {
471 #ifndef APP_ARG_RSZ_CHARS
472 #define APP_ARG_RSZ_CHARS 63
476 parse_arg_rsz(const char *arg
)
478 if (strnlen(arg
, APP_ARG_RSZ_CHARS
+ 1) == APP_ARG_RSZ_CHARS
+ 1) {
482 if (str_to_unsigned_vals(arg
, APP_ARG_RSZ_CHARS
, ',', 4,
483 &app
.nic_rx_ring_size
,
486 &app
.nic_tx_ring_size
) != 4)
490 if ((app
.nic_rx_ring_size
== 0) ||
491 (app
.nic_tx_ring_size
== 0) ||
492 (app
.ring_rx_size
== 0) ||
493 (app
.ring_tx_size
== 0)) {
500 #ifndef APP_ARG_BSZ_CHARS
501 #define APP_ARG_BSZ_CHARS 63
505 parse_arg_bsz(const char *arg
)
507 const char *p
= arg
, *p0
;
508 if (strnlen(arg
, APP_ARG_BSZ_CHARS
+ 1) == APP_ARG_BSZ_CHARS
+ 1) {
512 p0
= strchr(p
++, ')');
514 (str_to_unsigned_vals(p
, p0
- p
, ',', 2, &app
.burst_size_io_rx_read
, &app
.burst_size_io_rx_write
) != 2)) {
523 p0
= strchr(p
++, ')');
525 (str_to_unsigned_vals(p
, p0
- p
, ',', 2, &app
.burst_size_worker_read
, &app
.burst_size_worker_write
) != 2)) {
534 p0
= strchr(p
++, ')');
536 (str_to_unsigned_vals(p
, p0
- p
, ',', 2, &app
.burst_size_io_tx_read
, &app
.burst_size_io_tx_write
) != 2)) {
540 if ((app
.burst_size_io_rx_read
== 0) ||
541 (app
.burst_size_io_rx_write
== 0) ||
542 (app
.burst_size_worker_read
== 0) ||
543 (app
.burst_size_worker_write
== 0) ||
544 (app
.burst_size_io_tx_read
== 0) ||
545 (app
.burst_size_io_tx_write
== 0)) {
549 if ((app
.burst_size_io_rx_read
> APP_MBUF_ARRAY_SIZE
) ||
550 (app
.burst_size_io_rx_write
> APP_MBUF_ARRAY_SIZE
) ||
551 (app
.burst_size_worker_read
> APP_MBUF_ARRAY_SIZE
) ||
552 (app
.burst_size_worker_write
> APP_MBUF_ARRAY_SIZE
) ||
553 ((2 * app
.burst_size_io_tx_read
) > APP_MBUF_ARRAY_SIZE
) ||
554 (app
.burst_size_io_tx_write
> APP_MBUF_ARRAY_SIZE
)) {
561 #ifndef APP_ARG_NUMERICAL_SIZE_CHARS
562 #define APP_ARG_NUMERICAL_SIZE_CHARS 15
566 parse_arg_pos_lb(const char *arg
)
571 if (strnlen(arg
, APP_ARG_NUMERICAL_SIZE_CHARS
+ 1) == APP_ARG_NUMERICAL_SIZE_CHARS
+ 1) {
576 x
= strtoul(arg
, &endpt
, 10);
577 if (errno
!= 0 || endpt
== arg
|| *endpt
!= '\0'){
585 app
.pos_lb
= (uint8_t) x
;
590 /* Parse the argument given in the command line of the application */
592 app_parse_args(int argc
, char **argv
)
597 char *prgname
= argv
[0];
598 static struct option lgopts
[] = {
611 uint32_t arg_lpm
= 0;
612 uint32_t arg_rsz
= 0;
613 uint32_t arg_bsz
= 0;
614 uint32_t arg_pos_lb
= 0;
618 while ((opt
= getopt_long(argc
, argvopt
, "",
619 lgopts
, &option_index
)) != EOF
) {
624 if (!strcmp(lgopts
[option_index
].name
, "rx")) {
626 ret
= parse_arg_rx(optarg
);
628 printf("Incorrect value for --rx argument (%d)\n", ret
);
632 if (!strcmp(lgopts
[option_index
].name
, "tx")) {
634 ret
= parse_arg_tx(optarg
);
636 printf("Incorrect value for --tx argument (%d)\n", ret
);
640 if (!strcmp(lgopts
[option_index
].name
, "w")) {
642 ret
= parse_arg_w(optarg
);
644 printf("Incorrect value for --w argument (%d)\n", ret
);
648 if (!strcmp(lgopts
[option_index
].name
, "lpm")) {
650 ret
= parse_arg_lpm(optarg
);
652 printf("Incorrect value for --lpm argument (%d)\n", ret
);
656 if (!strcmp(lgopts
[option_index
].name
, "rsz")) {
658 ret
= parse_arg_rsz(optarg
);
660 printf("Incorrect value for --rsz argument (%d)\n", ret
);
664 if (!strcmp(lgopts
[option_index
].name
, "bsz")) {
666 ret
= parse_arg_bsz(optarg
);
668 printf("Incorrect value for --bsz argument (%d)\n", ret
);
672 if (!strcmp(lgopts
[option_index
].name
, "pos-lb")) {
674 ret
= parse_arg_pos_lb(optarg
);
676 printf("Incorrect value for --pos-lb argument (%d)\n", ret
);
687 /* Check that all mandatory arguments are provided */
688 if ((arg_rx
== 0) || (arg_tx
== 0) || (arg_w
== 0) || (arg_lpm
== 0)){
689 printf("Not all mandatory arguments are present\n");
693 /* Assign default values for the optional arguments not provided */
695 app
.nic_rx_ring_size
= APP_DEFAULT_NIC_RX_RING_SIZE
;
696 app
.nic_tx_ring_size
= APP_DEFAULT_NIC_TX_RING_SIZE
;
697 app
.ring_rx_size
= APP_DEFAULT_RING_RX_SIZE
;
698 app
.ring_tx_size
= APP_DEFAULT_RING_TX_SIZE
;
702 app
.burst_size_io_rx_read
= APP_DEFAULT_BURST_SIZE_IO_RX_READ
;
703 app
.burst_size_io_rx_write
= APP_DEFAULT_BURST_SIZE_IO_RX_WRITE
;
704 app
.burst_size_io_tx_read
= APP_DEFAULT_BURST_SIZE_IO_TX_READ
;
705 app
.burst_size_io_tx_write
= APP_DEFAULT_BURST_SIZE_IO_TX_WRITE
;
706 app
.burst_size_worker_read
= APP_DEFAULT_BURST_SIZE_WORKER_READ
;
707 app
.burst_size_worker_write
= APP_DEFAULT_BURST_SIZE_WORKER_WRITE
;
710 if (arg_pos_lb
== 0) {
711 app
.pos_lb
= APP_DEFAULT_IO_RX_LB_POS
;
714 /* Check cross-consistency of arguments */
715 if ((ret
= app_check_lpm_table()) < 0) {
716 printf("At least one LPM rule is inconsistent (%d)\n", ret
);
719 if (app_check_every_rx_port_is_tx_enabled() < 0) {
720 printf("On LPM lookup miss, packet is sent back on the input port.\n");
721 printf("At least one RX port is not enabled for TX.\n");
726 argv
[optind
- 1] = prgname
;
729 optind
= 1; /* reset getopt lib */
734 app_get_nic_rx_queues_per_port(uint16_t port
)
738 if (port
>= APP_MAX_NIC_PORTS
) {
743 for (i
= 0; i
< APP_MAX_RX_QUEUES_PER_NIC_PORT
; i
++) {
744 if (app
.nic_rx_queue_mask
[port
][i
] == 1) {
753 app_get_lcore_for_nic_rx(uint16_t port
, uint8_t queue
, uint32_t *lcore_out
)
757 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
758 struct app_lcore_params_io
*lp
= &app
.lcore_params
[lcore
].io
;
761 if (app
.lcore_params
[lcore
].type
!= e_APP_LCORE_IO
) {
765 const size_t n_queues
= RTE_MIN(lp
->rx
.n_nic_queues
,
766 RTE_DIM(lp
->rx
.nic_queues
));
767 for (i
= 0; i
< n_queues
; i
++) {
768 if ((lp
->rx
.nic_queues
[i
].port
== port
) &&
769 (lp
->rx
.nic_queues
[i
].queue
== queue
)) {
780 app_get_lcore_for_nic_tx(uint16_t port
, uint32_t *lcore_out
)
784 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
785 struct app_lcore_params_io
*lp
= &app
.lcore_params
[lcore
].io
;
788 if (app
.lcore_params
[lcore
].type
!= e_APP_LCORE_IO
) {
792 const size_t n_ports
= RTE_MIN(lp
->tx
.n_nic_ports
,
793 RTE_DIM(lp
->tx
.nic_ports
));
794 for (i
= 0; i
< n_ports
; i
++) {
795 if (lp
->tx
.nic_ports
[i
] == port
) {
806 app_is_socket_used(uint32_t socket
)
810 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
811 if (app
.lcore_params
[lcore
].type
== e_APP_LCORE_DISABLED
) {
815 if (socket
== rte_lcore_to_socket_id(lcore
)) {
824 app_get_lcores_io_rx(void)
826 uint32_t lcore
, count
;
829 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
830 struct app_lcore_params_io
*lp_io
= &app
.lcore_params
[lcore
].io
;
832 if ((app
.lcore_params
[lcore
].type
!= e_APP_LCORE_IO
) ||
833 (lp_io
->rx
.n_nic_queues
== 0)) {
844 app_get_lcores_worker(void)
846 uint32_t lcore
, count
;
849 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
850 if (app
.lcore_params
[lcore
].type
!= e_APP_LCORE_WORKER
) {
857 if (count
> APP_MAX_WORKER_LCORES
) {
858 rte_panic("Algorithmic error (too many worker lcores)\n");
866 app_print_params(void)
868 unsigned port
, queue
, lcore
, rule
, i
, j
;
870 /* Print NIC RX configuration */
871 printf("NIC RX ports: ");
872 for (port
= 0; port
< APP_MAX_NIC_PORTS
; port
++) {
873 uint32_t n_rx_queues
= app_get_nic_rx_queues_per_port(port
);
875 if (n_rx_queues
== 0) {
879 printf("%u (", port
);
880 for (queue
= 0; queue
< APP_MAX_RX_QUEUES_PER_NIC_PORT
; queue
++) {
881 if (app
.nic_rx_queue_mask
[port
][queue
] == 1) {
882 printf("%u ", queue
);
889 /* Print I/O lcore RX params */
890 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
891 struct app_lcore_params_io
*lp
= &app
.lcore_params
[lcore
].io
;
893 if ((app
.lcore_params
[lcore
].type
!= e_APP_LCORE_IO
) ||
894 (lp
->rx
.n_nic_queues
== 0)) {
898 printf("I/O lcore %u (socket %u): ", lcore
, rte_lcore_to_socket_id(lcore
));
901 for (i
= 0; i
< lp
->rx
.n_nic_queues
; i
++) {
903 (unsigned) lp
->rx
.nic_queues
[i
].port
,
904 (unsigned) lp
->rx
.nic_queues
[i
].queue
);
908 printf("Output rings ");
909 for (i
= 0; i
< lp
->rx
.n_rings
; i
++) {
910 printf("%p ", lp
->rx
.rings
[i
]);
915 /* Print worker lcore RX params */
916 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
917 struct app_lcore_params_worker
*lp
= &app
.lcore_params
[lcore
].worker
;
919 if (app
.lcore_params
[lcore
].type
!= e_APP_LCORE_WORKER
) {
923 printf("Worker lcore %u (socket %u) ID %u: ",
925 rte_lcore_to_socket_id(lcore
),
926 (unsigned)lp
->worker_id
);
928 printf("Input rings ");
929 for (i
= 0; i
< lp
->n_rings_in
; i
++) {
930 printf("%p ", lp
->rings_in
[i
]);
938 /* Print NIC TX configuration */
939 printf("NIC TX ports: ");
940 for (port
= 0; port
< APP_MAX_NIC_PORTS
; port
++) {
941 if (app
.nic_tx_port_mask
[port
] == 1) {
947 /* Print I/O TX lcore params */
948 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
949 struct app_lcore_params_io
*lp
= &app
.lcore_params
[lcore
].io
;
950 uint32_t n_workers
= app_get_lcores_worker();
952 if ((app
.lcore_params
[lcore
].type
!= e_APP_LCORE_IO
) ||
953 (lp
->tx
.n_nic_ports
== 0)) {
957 printf("I/O lcore %u (socket %u): ", lcore
, rte_lcore_to_socket_id(lcore
));
959 printf("Input rings per TX port ");
960 for (i
= 0; i
< lp
->tx
.n_nic_ports
; i
++) {
961 port
= lp
->tx
.nic_ports
[i
];
963 printf("%u (", port
);
964 for (j
= 0; j
< n_workers
; j
++) {
965 printf("%p ", lp
->tx
.rings
[port
][j
]);
974 /* Print worker lcore TX params */
975 for (lcore
= 0; lcore
< APP_MAX_LCORES
; lcore
++) {
976 struct app_lcore_params_worker
*lp
= &app
.lcore_params
[lcore
].worker
;
978 if (app
.lcore_params
[lcore
].type
!= e_APP_LCORE_WORKER
) {
982 printf("Worker lcore %u (socket %u) ID %u: \n",
984 rte_lcore_to_socket_id(lcore
),
985 (unsigned)lp
->worker_id
);
987 printf("Output rings per TX port ");
988 for (port
= 0; port
< APP_MAX_NIC_PORTS
; port
++) {
989 if (lp
->rings_out
[port
] != NULL
) {
990 printf("%u (%p) ", port
, lp
->rings_out
[port
]);
997 /* Print LPM rules */
998 printf("LPM rules: \n");
999 for (rule
= 0; rule
< app
.n_lpm_rules
; rule
++) {
1000 uint32_t ip
= app
.lpm_rules
[rule
].ip
;
1001 uint8_t depth
= app
.lpm_rules
[rule
].depth
;
1002 uint8_t if_out
= app
.lpm_rules
[rule
].if_out
;
1004 printf("\t%u: %u.%u.%u.%u/%u => %u;\n",
1006 (unsigned) (ip
& 0xFF000000) >> 24,
1007 (unsigned) (ip
& 0x00FF0000) >> 16,
1008 (unsigned) (ip
& 0x0000FF00) >> 8,
1009 (unsigned) ip
& 0x000000FF,
1016 printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n",
1017 (unsigned) app
.nic_rx_ring_size
,
1018 (unsigned) app
.ring_rx_size
,
1019 (unsigned) app
.ring_tx_size
,
1020 (unsigned) app
.nic_tx_ring_size
);
1023 printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n",
1024 (unsigned) app
.burst_size_io_rx_read
,
1025 (unsigned) app
.burst_size_io_rx_write
,
1026 (unsigned) app
.burst_size_worker_read
,
1027 (unsigned) app
.burst_size_worker_write
,
1028 (unsigned) app
.burst_size_io_tx_read
,
1029 (unsigned) app
.burst_size_io_tx_write
);