1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
11 #include <sys/queue.h>
16 #include <sys/param.h>
18 #include <rte_common.h>
19 #include <rte_byteorder.h>
21 #include <rte_memory.h>
22 #include <rte_memcpy.h>
24 #include <rte_launch.h>
25 #include <rte_atomic.h>
26 #include <rte_cycles.h>
27 #include <rte_prefetch.h>
28 #include <rte_lcore.h>
29 #include <rte_per_lcore.h>
30 #include <rte_branch_prediction.h>
31 #include <rte_interrupts.h>
32 #include <rte_random.h>
33 #include <rte_debug.h>
34 #include <rte_ether.h>
35 #include <rte_ethdev.h>
36 #include <rte_mempool.h>
38 #include <rte_malloc.h>
42 #include <rte_string_fns.h>
46 #include <rte_ip_frag.h>
48 #define MAX_PKT_BURST 32
51 #define RTE_LOGTYPE_IP_RSMBL RTE_LOGTYPE_USER1
53 #define MAX_JUMBO_PKT_LEN 9600
55 #define BUF_SIZE RTE_MBUF_DEFAULT_DATAROOM
56 #define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
59 #define MEMPOOL_CACHE_SIZE 256
61 /* allow max jumbo frame 9.5 KB */
62 #define JUMBO_FRAME_MAX_SIZE 0x2600
64 #define MAX_FLOW_NUM UINT16_MAX
65 #define MIN_FLOW_NUM 1
66 #define DEF_FLOW_NUM 0x1000
68 /* TTL numbers are in ms. */
69 #define MAX_FLOW_TTL (3600 * MS_PER_S)
70 #define MIN_FLOW_TTL 1
71 #define DEF_FLOW_TTL MS_PER_S
73 #define MAX_FRAG_NUM RTE_LIBRTE_IP_FRAG_MAX_FRAG
75 /* Should be power of two. */
76 #define IP_FRAG_TBL_BUCKET_ENTRIES 16
78 static uint32_t max_flow_num
= DEF_FLOW_NUM
;
79 static uint32_t max_flow_ttl
= DEF_FLOW_TTL
;
81 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
85 /* Configure how many packets ahead to prefetch, when reading packets */
86 #define PREFETCH_OFFSET 3
89 * Configurable number of RX/TX ring descriptors
91 #define RTE_TEST_RX_DESC_DEFAULT 1024
92 #define RTE_TEST_TX_DESC_DEFAULT 1024
94 static uint16_t nb_rxd
= RTE_TEST_RX_DESC_DEFAULT
;
95 static uint16_t nb_txd
= RTE_TEST_TX_DESC_DEFAULT
;
97 /* ethernet addresses of ports */
98 static struct ether_addr ports_eth_addr
[RTE_MAX_ETHPORTS
];
101 #define IPv4_BYTES_FMT "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
102 #define IPv4_BYTES(addr) \
103 (uint8_t) (((addr) >> 24) & 0xFF),\
104 (uint8_t) (((addr) >> 16) & 0xFF),\
105 (uint8_t) (((addr) >> 8) & 0xFF),\
106 (uint8_t) ((addr) & 0xFF)
110 #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\
111 "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
112 #define IPv6_BYTES(addr) \
113 addr[0], addr[1], addr[2], addr[3], \
114 addr[4], addr[5], addr[6], addr[7], \
115 addr[8], addr[9], addr[10], addr[11],\
116 addr[12], addr[13],addr[14], addr[15]
119 #define IPV6_ADDR_LEN 16
121 /* mask of enabled ports */
122 static uint32_t enabled_port_mask
= 0;
124 static int rx_queue_per_lcore
= 1;
130 struct rte_mbuf
*m_table
[0];
134 struct rte_ip_frag_tbl
*frag_tbl
;
135 struct rte_mempool
*pool
;
137 struct rte_lpm6
*lpm6
;
141 struct tx_lcore_stat
{
148 #define MAX_RX_QUEUE_PER_LCORE 16
149 #define MAX_TX_QUEUE_PER_PORT 16
150 #define MAX_RX_QUEUE_PER_PORT 128
152 struct lcore_queue_conf
{
154 struct rx_queue rx_queue_list
[MAX_RX_QUEUE_PER_LCORE
];
155 uint16_t tx_queue_id
[RTE_MAX_ETHPORTS
];
156 struct rte_ip_frag_death_row death_row
;
157 struct mbuf_table
*tx_mbufs
[RTE_MAX_ETHPORTS
];
158 struct tx_lcore_stat tx_stat
;
159 } __rte_cache_aligned
;
160 static struct lcore_queue_conf lcore_queue_conf
[RTE_MAX_LCORE
];
162 static struct rte_eth_conf port_conf
= {
164 .mq_mode
= ETH_MQ_RX_RSS
,
165 .max_rx_pkt_len
= JUMBO_FRAME_MAX_SIZE
,
167 .offloads
= (DEV_RX_OFFLOAD_CHECKSUM
|
168 DEV_RX_OFFLOAD_JUMBO_FRAME
),
173 .rss_hf
= ETH_RSS_IP
,
177 .mq_mode
= ETH_MQ_TX_NONE
,
178 .offloads
= (DEV_TX_OFFLOAD_IPV4_CKSUM
|
179 DEV_TX_OFFLOAD_MULTI_SEGS
),
184 * IPv4 forwarding table
186 struct l3fwd_ipv4_route
{
192 struct l3fwd_ipv4_route l3fwd_ipv4_route_array
[] = {
193 {IPv4(100,10,0,0), 16, 0},
194 {IPv4(100,20,0,0), 16, 1},
195 {IPv4(100,30,0,0), 16, 2},
196 {IPv4(100,40,0,0), 16, 3},
197 {IPv4(100,50,0,0), 16, 4},
198 {IPv4(100,60,0,0), 16, 5},
199 {IPv4(100,70,0,0), 16, 6},
200 {IPv4(100,80,0,0), 16, 7},
204 * IPv6 forwarding table
207 struct l3fwd_ipv6_route
{
208 uint8_t ip
[IPV6_ADDR_LEN
];
213 static struct l3fwd_ipv6_route l3fwd_ipv6_route_array
[] = {
214 {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0},
215 {{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1},
216 {{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2},
217 {{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3},
218 {{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4},
219 {{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5},
220 {{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6},
221 {{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7},
224 #define LPM_MAX_RULES 1024
225 #define LPM6_MAX_RULES 1024
226 #define LPM6_NUMBER_TBL8S (1 << 16)
228 struct rte_lpm6_config lpm6_config
= {
229 .max_rules
= LPM6_MAX_RULES
,
230 .number_tbl8s
= LPM6_NUMBER_TBL8S
,
234 static struct rte_lpm
*socket_lpm
[RTE_MAX_NUMA_NODES
];
235 static struct rte_lpm6
*socket_lpm6
[RTE_MAX_NUMA_NODES
];
237 #ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT
238 #define TX_LCORE_STAT_UPDATE(s, f, v) ((s)->f += (v))
240 #define TX_LCORE_STAT_UPDATE(s, f, v) do {} while (0)
241 #endif /* RTE_LIBRTE_IP_FRAG_TBL_STAT */
244 * If number of queued packets reached given threahold, then
245 * send burst of packets on an output interface.
247 static inline uint32_t
248 send_burst(struct lcore_queue_conf
*qconf
, uint32_t thresh
, uint16_t port
)
250 uint32_t fill
, len
, k
, n
;
251 struct mbuf_table
*txmb
;
253 txmb
= qconf
->tx_mbufs
[port
];
256 if ((int32_t)(fill
= txmb
->head
- txmb
->tail
) < 0)
259 if (fill
>= thresh
) {
260 n
= RTE_MIN(len
- txmb
->tail
, fill
);
262 k
= rte_eth_tx_burst(port
, qconf
->tx_queue_id
[port
],
263 txmb
->m_table
+ txmb
->tail
, (uint16_t)n
);
265 TX_LCORE_STAT_UPDATE(&qconf
->tx_stat
, call
, 1);
266 TX_LCORE_STAT_UPDATE(&qconf
->tx_stat
, send
, k
);
269 if ((txmb
->tail
+= k
) == len
)
276 /* Enqueue a single packet, and send burst if queue is filled */
278 send_single_packet(struct rte_mbuf
*m
, uint16_t port
)
280 uint32_t fill
, lcore_id
, len
;
281 struct lcore_queue_conf
*qconf
;
282 struct mbuf_table
*txmb
;
284 lcore_id
= rte_lcore_id();
285 qconf
= &lcore_queue_conf
[lcore_id
];
287 txmb
= qconf
->tx_mbufs
[port
];
290 fill
= send_burst(qconf
, MAX_PKT_BURST
, port
);
292 if (fill
== len
- 1) {
293 TX_LCORE_STAT_UPDATE(&qconf
->tx_stat
, drop
, 1);
294 rte_pktmbuf_free(txmb
->m_table
[txmb
->tail
]);
295 if (++txmb
->tail
== len
)
299 TX_LCORE_STAT_UPDATE(&qconf
->tx_stat
, queue
, 1);
300 txmb
->m_table
[txmb
->head
] = m
;
301 if(++txmb
->head
== len
)
308 reassemble(struct rte_mbuf
*m
, uint16_t portid
, uint32_t queue
,
309 struct lcore_queue_conf
*qconf
, uint64_t tms
)
311 struct ether_hdr
*eth_hdr
;
312 struct rte_ip_frag_tbl
*tbl
;
313 struct rte_ip_frag_death_row
*dr
;
314 struct rx_queue
*rxq
;
319 rxq
= &qconf
->rx_queue_list
[queue
];
321 eth_hdr
= rte_pktmbuf_mtod(m
, struct ether_hdr
*);
325 /* if packet is IPv4 */
326 if (RTE_ETH_IS_IPV4_HDR(m
->packet_type
)) {
327 struct ipv4_hdr
*ip_hdr
;
330 ip_hdr
= (struct ipv4_hdr
*)(eth_hdr
+ 1);
332 /* if it is a fragmented packet, then try to reassemble. */
333 if (rte_ipv4_frag_pkt_is_fragmented(ip_hdr
)) {
337 dr
= &qconf
->death_row
;
339 /* prepare mbuf: setup l2_len/l3_len. */
340 m
->l2_len
= sizeof(*eth_hdr
);
341 m
->l3_len
= sizeof(*ip_hdr
);
343 /* process this fragment. */
344 mo
= rte_ipv4_frag_reassemble_packet(tbl
, dr
, m
, tms
, ip_hdr
);
346 /* no packet to send out. */
349 /* we have our packet reassembled. */
352 eth_hdr
= rte_pktmbuf_mtod(m
,
354 ip_hdr
= (struct ipv4_hdr
*)(eth_hdr
+ 1);
357 ip_dst
= rte_be_to_cpu_32(ip_hdr
->dst_addr
);
359 /* Find destination port */
360 if (rte_lpm_lookup(rxq
->lpm
, ip_dst
, &next_hop
) == 0 &&
361 (enabled_port_mask
& 1 << next_hop
) != 0) {
365 eth_hdr
->ether_type
= rte_be_to_cpu_16(ETHER_TYPE_IPv4
);
366 } else if (RTE_ETH_IS_IPV6_HDR(m
->packet_type
)) {
367 /* if packet is IPv6 */
368 struct ipv6_extension_fragment
*frag_hdr
;
369 struct ipv6_hdr
*ip_hdr
;
371 ip_hdr
= (struct ipv6_hdr
*)(eth_hdr
+ 1);
373 frag_hdr
= rte_ipv6_frag_get_ipv6_fragment_header(ip_hdr
);
375 if (frag_hdr
!= NULL
) {
379 dr
= &qconf
->death_row
;
381 /* prepare mbuf: setup l2_len/l3_len. */
382 m
->l2_len
= sizeof(*eth_hdr
);
383 m
->l3_len
= sizeof(*ip_hdr
) + sizeof(*frag_hdr
);
385 mo
= rte_ipv6_frag_reassemble_packet(tbl
, dr
, m
, tms
, ip_hdr
, frag_hdr
);
391 eth_hdr
= rte_pktmbuf_mtod(m
, struct ether_hdr
*);
392 ip_hdr
= (struct ipv6_hdr
*)(eth_hdr
+ 1);
396 /* Find destination port */
397 if (rte_lpm6_lookup(rxq
->lpm6
, ip_hdr
->dst_addr
,
399 (enabled_port_mask
& 1 << next_hop
) != 0) {
403 eth_hdr
->ether_type
= rte_be_to_cpu_16(ETHER_TYPE_IPv6
);
405 /* if packet wasn't IPv4 or IPv6, it's forwarded to the port it came from */
407 /* 02:00:00:00:00:xx */
408 d_addr_bytes
= ð_hdr
->d_addr
.addr_bytes
[0];
409 *((uint64_t *)d_addr_bytes
) = 0x000000000002 + ((uint64_t)dst_port
<< 40);
412 ether_addr_copy(&ports_eth_addr
[dst_port
], ð_hdr
->s_addr
);
414 send_single_packet(m
, dst_port
);
417 /* main processing loop */
419 main_loop(__attribute__((unused
)) void *dummy
)
421 struct rte_mbuf
*pkts_burst
[MAX_PKT_BURST
];
423 uint64_t diff_tsc
, cur_tsc
, prev_tsc
;
426 struct lcore_queue_conf
*qconf
;
427 const uint64_t drain_tsc
= (rte_get_tsc_hz() + US_PER_S
- 1) / US_PER_S
* BURST_TX_DRAIN_US
;
431 lcore_id
= rte_lcore_id();
432 qconf
= &lcore_queue_conf
[lcore_id
];
434 if (qconf
->n_rx_queue
== 0) {
435 RTE_LOG(INFO
, IP_RSMBL
, "lcore %u has nothing to do\n", lcore_id
);
439 RTE_LOG(INFO
, IP_RSMBL
, "entering main loop on lcore %u\n", lcore_id
);
441 for (i
= 0; i
< qconf
->n_rx_queue
; i
++) {
443 portid
= qconf
->rx_queue_list
[i
].portid
;
444 RTE_LOG(INFO
, IP_RSMBL
, " -- lcoreid=%u portid=%u\n", lcore_id
,
450 cur_tsc
= rte_rdtsc();
453 * TX burst queue drain
455 diff_tsc
= cur_tsc
- prev_tsc
;
456 if (unlikely(diff_tsc
> drain_tsc
)) {
459 * This could be optimized (use queueid instead of
460 * portid), but it is not called so often
462 for (portid
= 0; portid
< RTE_MAX_ETHPORTS
; portid
++) {
463 if ((enabled_port_mask
& (1 << portid
)) != 0)
464 send_burst(qconf
, 1, portid
);
471 * Read packet from RX queues
473 for (i
= 0; i
< qconf
->n_rx_queue
; ++i
) {
475 portid
= qconf
->rx_queue_list
[i
].portid
;
477 nb_rx
= rte_eth_rx_burst(portid
, 0, pkts_burst
,
480 /* Prefetch first packets */
481 for (j
= 0; j
< PREFETCH_OFFSET
&& j
< nb_rx
; j
++) {
482 rte_prefetch0(rte_pktmbuf_mtod(
483 pkts_burst
[j
], void *));
486 /* Prefetch and forward already prefetched packets */
487 for (j
= 0; j
< (nb_rx
- PREFETCH_OFFSET
); j
++) {
488 rte_prefetch0(rte_pktmbuf_mtod(pkts_burst
[
489 j
+ PREFETCH_OFFSET
], void *));
490 reassemble(pkts_burst
[j
], portid
,
494 /* Forward remaining prefetched packets */
495 for (; j
< nb_rx
; j
++) {
496 reassemble(pkts_burst
[j
], portid
,
500 rte_ip_frag_free_death_row(&qconf
->death_row
,
508 print_usage(const char *prgname
)
510 printf("%s [EAL options] -- -p PORTMASK [-q NQ]"
511 " [--max-pkt-len PKTLEN]"
512 " [--maxflows=<flows>] [--flowttl=<ttl>[(s|ms)]]\n"
513 " -p PORTMASK: hexadecimal bitmask of ports to configure\n"
514 " -q NQ: number of RX queues per lcore\n"
515 " --maxflows=<flows>: optional, maximum number of flows "
517 " --flowttl=<ttl>[(s|ms)]: optional, maximum TTL for each "
523 parse_flow_num(const char *str
, uint32_t min
, uint32_t max
, uint32_t *val
)
528 /* parse decimal string */
530 v
= strtoul(str
, &end
, 10);
531 if (errno
!= 0 || *end
!= '\0')
534 if (v
< min
|| v
> max
)
542 parse_flow_ttl(const char *str
, uint32_t min
, uint32_t max
, uint32_t *val
)
547 static const char frmt_sec
[] = "s";
548 static const char frmt_msec
[] = "ms";
550 /* parse decimal string */
552 v
= strtoul(str
, &end
, 10);
557 if (strncmp(frmt_sec
, end
, sizeof(frmt_sec
)) == 0)
559 else if (strncmp(frmt_msec
, end
, sizeof (frmt_msec
)) != 0)
563 if (v
< min
|| v
> max
)
571 parse_portmask(const char *portmask
)
576 /* parse hexadecimal string */
577 pm
= strtoul(portmask
, &end
, 16);
578 if ((portmask
[0] == '\0') || (end
== NULL
) || (*end
!= '\0'))
588 parse_nqueue(const char *q_arg
)
593 printf("%p\n", q_arg
);
595 /* parse hexadecimal string */
596 n
= strtoul(q_arg
, &end
, 10);
597 if ((q_arg
[0] == '\0') || (end
== NULL
) || (*end
!= '\0'))
601 if (n
>= MAX_RX_QUEUE_PER_LCORE
)
607 /* Parse the argument given in the command line of the application */
609 parse_args(int argc
, char **argv
)
614 char *prgname
= argv
[0];
615 static struct option lgopts
[] = {
616 {"max-pkt-len", 1, 0, 0},
617 {"maxflows", 1, 0, 0},
618 {"flowttl", 1, 0, 0},
624 while ((opt
= getopt_long(argc
, argvopt
, "p:q:",
625 lgopts
, &option_index
)) != EOF
) {
630 enabled_port_mask
= parse_portmask(optarg
);
631 if (enabled_port_mask
== 0) {
632 printf("invalid portmask\n");
633 print_usage(prgname
);
640 rx_queue_per_lcore
= parse_nqueue(optarg
);
641 if (rx_queue_per_lcore
< 0) {
642 printf("invalid queue number\n");
643 print_usage(prgname
);
650 if (!strncmp(lgopts
[option_index
].name
,
652 if ((ret
= parse_flow_num(optarg
, MIN_FLOW_NUM
,
654 &max_flow_num
)) != 0) {
655 printf("invalid value: \"%s\" for "
658 lgopts
[option_index
].name
);
659 print_usage(prgname
);
664 if (!strncmp(lgopts
[option_index
].name
, "flowttl", 7)) {
665 if ((ret
= parse_flow_ttl(optarg
, MIN_FLOW_TTL
,
667 &max_flow_ttl
)) != 0) {
668 printf("invalid value: \"%s\" for "
671 lgopts
[option_index
].name
);
672 print_usage(prgname
);
680 print_usage(prgname
);
686 argv
[optind
-1] = prgname
;
689 optind
= 1; /* reset getopt lib */
694 print_ethaddr(const char *name
, const struct ether_addr
*eth_addr
)
696 char buf
[ETHER_ADDR_FMT_SIZE
];
697 ether_format_addr(buf
, ETHER_ADDR_FMT_SIZE
, eth_addr
);
698 printf("%s%s", name
, buf
);
701 /* Check the link status of all ports in up to 9s, and print them finally */
703 check_all_ports_link_status(uint32_t port_mask
)
705 #define CHECK_INTERVAL 100 /* 100ms */
706 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
708 uint8_t count
, all_ports_up
, print_flag
= 0;
709 struct rte_eth_link link
;
711 printf("\nChecking link status");
713 for (count
= 0; count
<= MAX_CHECK_TIME
; count
++) {
715 RTE_ETH_FOREACH_DEV(portid
) {
716 if ((port_mask
& (1 << portid
)) == 0)
718 memset(&link
, 0, sizeof(link
));
719 rte_eth_link_get_nowait(portid
, &link
);
720 /* print link status if flag set */
721 if (print_flag
== 1) {
722 if (link
.link_status
)
724 "Port%d Link Up. Speed %u Mbps - %s\n",
725 portid
, link
.link_speed
,
726 (link
.link_duplex
== ETH_LINK_FULL_DUPLEX
) ?
727 ("full-duplex") : ("half-duplex\n"));
729 printf("Port %d Link Down\n", portid
);
732 /* clear all_ports_up flag if any link down */
733 if (link
.link_status
== ETH_LINK_DOWN
) {
738 /* after finally printing all link status, get out */
742 if (all_ports_up
== 0) {
745 rte_delay_ms(CHECK_INTERVAL
);
748 /* set the print_flag if all ports up or timeout */
749 if (all_ports_up
== 1 || count
== (MAX_CHECK_TIME
- 1)) {
757 init_routing_table(void)
760 struct rte_lpm6
*lpm6
;
764 for (socket
= 0; socket
< RTE_MAX_NUMA_NODES
; socket
++) {
765 if (socket_lpm
[socket
]) {
766 lpm
= socket_lpm
[socket
];
767 /* populate the LPM table */
768 for (i
= 0; i
< RTE_DIM(l3fwd_ipv4_route_array
); i
++) {
769 ret
= rte_lpm_add(lpm
,
770 l3fwd_ipv4_route_array
[i
].ip
,
771 l3fwd_ipv4_route_array
[i
].depth
,
772 l3fwd_ipv4_route_array
[i
].if_out
);
775 RTE_LOG(ERR
, IP_RSMBL
, "Unable to add entry %i to the l3fwd "
780 RTE_LOG(INFO
, IP_RSMBL
, "Socket %i: adding route " IPv4_BYTES_FMT
783 IPv4_BYTES(l3fwd_ipv4_route_array
[i
].ip
),
784 l3fwd_ipv4_route_array
[i
].depth
,
785 l3fwd_ipv4_route_array
[i
].if_out
);
789 if (socket_lpm6
[socket
]) {
790 lpm6
= socket_lpm6
[socket
];
791 /* populate the LPM6 table */
792 for (i
= 0; i
< RTE_DIM(l3fwd_ipv6_route_array
); i
++) {
793 ret
= rte_lpm6_add(lpm6
,
794 l3fwd_ipv6_route_array
[i
].ip
,
795 l3fwd_ipv6_route_array
[i
].depth
,
796 l3fwd_ipv6_route_array
[i
].if_out
);
799 RTE_LOG(ERR
, IP_RSMBL
, "Unable to add entry %i to the l3fwd "
804 RTE_LOG(INFO
, IP_RSMBL
, "Socket %i: adding route " IPv6_BYTES_FMT
807 IPv6_BYTES(l3fwd_ipv6_route_array
[i
].ip
),
808 l3fwd_ipv6_route_array
[i
].depth
,
809 l3fwd_ipv6_route_array
[i
].if_out
);
817 setup_port_tbl(struct lcore_queue_conf
*qconf
, uint32_t lcore
, int socket
,
820 struct mbuf_table
*mtb
;
824 n
= RTE_MAX(max_flow_num
, 2UL * MAX_PKT_BURST
);
825 sz
= sizeof (*mtb
) + sizeof (mtb
->m_table
[0]) * n
;
827 if ((mtb
= rte_zmalloc_socket(__func__
, sz
, RTE_CACHE_LINE_SIZE
,
829 RTE_LOG(ERR
, IP_RSMBL
, "%s() for lcore: %u, port: %u "
830 "failed to allocate %zu bytes\n",
831 __func__
, lcore
, port
, sz
);
836 qconf
->tx_mbufs
[port
] = mtb
;
842 setup_queue_tbl(struct rx_queue
*rxq
, uint32_t lcore
, uint32_t queue
)
846 uint64_t frag_cycles
;
847 char buf
[RTE_MEMPOOL_NAMESIZE
];
849 socket
= rte_lcore_to_socket_id(lcore
);
850 if (socket
== SOCKET_ID_ANY
)
853 frag_cycles
= (rte_get_tsc_hz() + MS_PER_S
- 1) / MS_PER_S
*
856 if ((rxq
->frag_tbl
= rte_ip_frag_table_create(max_flow_num
,
857 IP_FRAG_TBL_BUCKET_ENTRIES
, max_flow_num
, frag_cycles
,
859 RTE_LOG(ERR
, IP_RSMBL
, "ip_frag_tbl_create(%u) on "
860 "lcore: %u for queue: %u failed\n",
861 max_flow_num
, lcore
, queue
);
866 * At any given moment up to <max_flow_num * (MAX_FRAG_NUM)>
867 * mbufs could be stored int the fragment table.
868 * Plus, each TX queue can hold up to <max_flow_num> packets.
871 nb_mbuf
= RTE_MAX(max_flow_num
, 2UL * MAX_PKT_BURST
) * MAX_FRAG_NUM
;
872 nb_mbuf
*= (port_conf
.rxmode
.max_rx_pkt_len
+ BUF_SIZE
- 1) / BUF_SIZE
;
873 nb_mbuf
*= 2; /* ipv4 and ipv6 */
874 nb_mbuf
+= nb_rxd
+ nb_txd
;
876 nb_mbuf
= RTE_MAX(nb_mbuf
, (uint32_t)NB_MBUF
);
878 snprintf(buf
, sizeof(buf
), "mbuf_pool_%u_%u", lcore
, queue
);
880 rxq
->pool
= rte_pktmbuf_pool_create(buf
, nb_mbuf
, MEMPOOL_CACHE_SIZE
, 0,
881 MBUF_DATA_SIZE
, socket
);
882 if (rxq
->pool
== NULL
) {
883 RTE_LOG(ERR
, IP_RSMBL
,
884 "rte_pktmbuf_pool_create(%s) failed", buf
);
896 struct rte_lpm6
*lpm6
;
897 struct rte_lpm_config lpm_config
;
901 /* traverse through lcores and initialize structures on each socket */
903 for (lcore_id
= 0; lcore_id
< RTE_MAX_LCORE
; lcore_id
++) {
905 if (rte_lcore_is_enabled(lcore_id
) == 0)
908 socket
= rte_lcore_to_socket_id(lcore_id
);
910 if (socket
== SOCKET_ID_ANY
)
913 if (socket_lpm
[socket
] == NULL
) {
914 RTE_LOG(INFO
, IP_RSMBL
, "Creating LPM table on socket %i\n", socket
);
915 snprintf(buf
, sizeof(buf
), "IP_RSMBL_LPM_%i", socket
);
917 lpm_config
.max_rules
= LPM_MAX_RULES
;
918 lpm_config
.number_tbl8s
= 256;
919 lpm_config
.flags
= 0;
921 lpm
= rte_lpm_create(buf
, socket
, &lpm_config
);
923 RTE_LOG(ERR
, IP_RSMBL
, "Cannot create LPM table\n");
926 socket_lpm
[socket
] = lpm
;
929 if (socket_lpm6
[socket
] == NULL
) {
930 RTE_LOG(INFO
, IP_RSMBL
, "Creating LPM6 table on socket %i\n", socket
);
931 snprintf(buf
, sizeof(buf
), "IP_RSMBL_LPM_%i", socket
);
933 lpm6
= rte_lpm6_create(buf
, socket
, &lpm6_config
);
935 RTE_LOG(ERR
, IP_RSMBL
, "Cannot create LPM table\n");
938 socket_lpm6
[socket
] = lpm6
;
946 queue_dump_stat(void)
949 const struct lcore_queue_conf
*qconf
;
951 for (lcore
= 0; lcore
< RTE_MAX_LCORE
; lcore
++) {
952 if (rte_lcore_is_enabled(lcore
) == 0)
955 qconf
= &lcore_queue_conf
[lcore
];
956 for (i
= 0; i
< qconf
->n_rx_queue
; i
++) {
958 fprintf(stdout
, " -- lcoreid=%u portid=%u "
960 lcore
, qconf
->rx_queue_list
[i
].portid
);
961 rte_ip_frag_table_statistics_dump(stdout
,
962 qconf
->rx_queue_list
[i
].frag_tbl
);
963 fprintf(stdout
, "TX bursts:\t%" PRIu64
"\n"
964 "TX packets _queued:\t%" PRIu64
"\n"
965 "TX packets dropped:\t%" PRIu64
"\n"
966 "TX packets send:\t%" PRIu64
"\n",
968 qconf
->tx_stat
.queue
,
970 qconf
->tx_stat
.send
);
976 signal_handler(int signum
)
979 if (signum
!= SIGUSR1
)
980 rte_exit(0, "received signal: %d, exiting\n", signum
);
984 main(int argc
, char **argv
)
986 struct lcore_queue_conf
*qconf
;
987 struct rte_eth_dev_info dev_info
;
988 struct rte_eth_txconf
*txconf
;
989 struct rx_queue
*rxq
;
993 unsigned lcore_id
= 0, rx_lcore_id
= 0;
994 uint32_t n_tx_queue
, nb_lcores
;
998 ret
= rte_eal_init(argc
, argv
);
1000 rte_exit(EXIT_FAILURE
, "Invalid EAL parameters\n");
1004 /* parse application arguments (after the EAL ones) */
1005 ret
= parse_args(argc
, argv
);
1007 rte_exit(EXIT_FAILURE
, "Invalid IP reassembly parameters\n");
1009 nb_ports
= rte_eth_dev_count_avail();
1011 rte_exit(EXIT_FAILURE
, "No ports found!\n");
1013 nb_lcores
= rte_lcore_count();
1015 /* initialize structures (mempools, lpm etc.) */
1017 rte_panic("Cannot initialize memory structures!\n");
1019 /* check if portmask has non-existent ports */
1020 if (enabled_port_mask
& ~(RTE_LEN2MASK(nb_ports
, unsigned)))
1021 rte_exit(EXIT_FAILURE
, "Non-existent ports in portmask!\n");
1023 /* initialize all ports */
1024 RTE_ETH_FOREACH_DEV(portid
) {
1025 struct rte_eth_rxconf rxq_conf
;
1026 struct rte_eth_conf local_port_conf
= port_conf
;
1028 /* skip ports that are not enabled */
1029 if ((enabled_port_mask
& (1 << portid
)) == 0) {
1030 printf("\nSkipping disabled port %d\n", portid
);
1034 qconf
= &lcore_queue_conf
[rx_lcore_id
];
1036 /* limit the frame size to the maximum supported by NIC */
1037 rte_eth_dev_info_get(portid
, &dev_info
);
1038 local_port_conf
.rxmode
.max_rx_pkt_len
= RTE_MIN(
1039 dev_info
.max_rx_pktlen
,
1040 local_port_conf
.rxmode
.max_rx_pkt_len
);
1042 /* get the lcore_id for this port */
1043 while (rte_lcore_is_enabled(rx_lcore_id
) == 0 ||
1044 qconf
->n_rx_queue
== (unsigned)rx_queue_per_lcore
) {
1047 if (rx_lcore_id
>= RTE_MAX_LCORE
)
1048 rte_exit(EXIT_FAILURE
, "Not enough cores\n");
1050 qconf
= &lcore_queue_conf
[rx_lcore_id
];
1053 socket
= rte_lcore_to_socket_id(portid
);
1054 if (socket
== SOCKET_ID_ANY
)
1057 queueid
= qconf
->n_rx_queue
;
1058 rxq
= &qconf
->rx_queue_list
[queueid
];
1059 rxq
->portid
= portid
;
1060 rxq
->lpm
= socket_lpm
[socket
];
1061 rxq
->lpm6
= socket_lpm6
[socket
];
1063 ret
= rte_eth_dev_adjust_nb_rx_tx_desc(portid
, &nb_rxd
,
1066 rte_exit(EXIT_FAILURE
,
1067 "Cannot adjust number of descriptors: err=%d, port=%d\n",
1070 if (setup_queue_tbl(rxq
, rx_lcore_id
, queueid
) < 0)
1071 rte_exit(EXIT_FAILURE
, "Failed to set up queue table\n");
1072 qconf
->n_rx_queue
++;
1075 printf("Initializing port %d ... ", portid
);
1078 n_tx_queue
= nb_lcores
;
1079 if (n_tx_queue
> MAX_TX_QUEUE_PER_PORT
)
1080 n_tx_queue
= MAX_TX_QUEUE_PER_PORT
;
1081 if (dev_info
.tx_offload_capa
& DEV_TX_OFFLOAD_MBUF_FAST_FREE
)
1082 local_port_conf
.txmode
.offloads
|=
1083 DEV_TX_OFFLOAD_MBUF_FAST_FREE
;
1085 local_port_conf
.rx_adv_conf
.rss_conf
.rss_hf
&=
1086 dev_info
.flow_type_rss_offloads
;
1087 if (local_port_conf
.rx_adv_conf
.rss_conf
.rss_hf
!=
1088 port_conf
.rx_adv_conf
.rss_conf
.rss_hf
) {
1089 printf("Port %u modified RSS hash function based on hardware support,"
1090 "requested:%#"PRIx64
" configured:%#"PRIx64
"\n",
1092 port_conf
.rx_adv_conf
.rss_conf
.rss_hf
,
1093 local_port_conf
.rx_adv_conf
.rss_conf
.rss_hf
);
1096 ret
= rte_eth_dev_configure(portid
, 1, (uint16_t)n_tx_queue
,
1100 rte_exit(EXIT_FAILURE
, "Cannot configure device: "
1101 "err=%d, port=%d\n",
1105 /* init one RX queue */
1106 rxq_conf
= dev_info
.default_rxconf
;
1107 rxq_conf
.offloads
= local_port_conf
.rxmode
.offloads
;
1108 ret
= rte_eth_rx_queue_setup(portid
, 0, nb_rxd
,
1113 rte_exit(EXIT_FAILURE
, "rte_eth_rx_queue_setup: "
1114 "err=%d, port=%d\n",
1118 rte_eth_macaddr_get(portid
, &ports_eth_addr
[portid
]);
1119 print_ethaddr(" Address:", &ports_eth_addr
[portid
]);
1122 /* init one TX queue per couple (lcore,port) */
1124 for (lcore_id
= 0; lcore_id
< RTE_MAX_LCORE
; lcore_id
++) {
1125 if (rte_lcore_is_enabled(lcore_id
) == 0)
1128 socket
= (int) rte_lcore_to_socket_id(lcore_id
);
1130 printf("txq=%u,%d,%d ", lcore_id
, queueid
, socket
);
1133 txconf
= &dev_info
.default_txconf
;
1134 txconf
->offloads
= local_port_conf
.txmode
.offloads
;
1136 ret
= rte_eth_tx_queue_setup(portid
, queueid
, nb_txd
,
1139 rte_exit(EXIT_FAILURE
, "rte_eth_tx_queue_setup: err=%d, "
1140 "port=%d\n", ret
, portid
);
1142 qconf
= &lcore_queue_conf
[lcore_id
];
1143 qconf
->tx_queue_id
[portid
] = queueid
;
1144 setup_port_tbl(qconf
, lcore_id
, socket
, portid
);
1153 RTE_ETH_FOREACH_DEV(portid
) {
1154 if ((enabled_port_mask
& (1 << portid
)) == 0) {
1158 ret
= rte_eth_dev_start(portid
);
1160 rte_exit(EXIT_FAILURE
, "rte_eth_dev_start: err=%d, port=%d\n",
1163 rte_eth_promiscuous_enable(portid
);
1166 if (init_routing_table() < 0)
1167 rte_exit(EXIT_FAILURE
, "Cannot init routing table\n");
1169 check_all_ports_link_status(enabled_port_mask
);
1171 signal(SIGUSR1
, signal_handler
);
1172 signal(SIGTERM
, signal_handler
);
1173 signal(SIGINT
, signal_handler
);
1175 /* launch per-lcore init on every lcore */
1176 rte_eal_mp_remote_launch(main_loop
, NULL
, CALL_MASTER
);
1177 RTE_LCORE_FOREACH_SLAVE(lcore_id
) {
1178 if (rte_eal_wait_lcore(lcore_id
) < 0)