xref: /dpdk/examples/l3fwd-graph/main.c (revision a2bc05846c5bdd839ba9d13e65b02b981ea98130)
108bd1a17SNithin Dabilpuram /* SPDX-License-Identifier: BSD-3-Clause
208bd1a17SNithin Dabilpuram  * Copyright(C) 2020 Marvell International Ltd.
308bd1a17SNithin Dabilpuram  */
408bd1a17SNithin Dabilpuram 
508bd1a17SNithin Dabilpuram #include <arpa/inet.h>
608bd1a17SNithin Dabilpuram #include <errno.h>
708bd1a17SNithin Dabilpuram #include <getopt.h>
808bd1a17SNithin Dabilpuram #include <inttypes.h>
908bd1a17SNithin Dabilpuram #include <signal.h>
1008bd1a17SNithin Dabilpuram #include <stdarg.h>
1108bd1a17SNithin Dabilpuram #include <stdbool.h>
1208bd1a17SNithin Dabilpuram #include <stdint.h>
1308bd1a17SNithin Dabilpuram #include <stdio.h>
1408bd1a17SNithin Dabilpuram #include <stdlib.h>
1508bd1a17SNithin Dabilpuram #include <string.h>
1608bd1a17SNithin Dabilpuram #include <sys/socket.h>
1708bd1a17SNithin Dabilpuram #include <sys/types.h>
1808bd1a17SNithin Dabilpuram #include <sys/queue.h>
1908bd1a17SNithin Dabilpuram #include <unistd.h>
2008bd1a17SNithin Dabilpuram 
2108bd1a17SNithin Dabilpuram #include <rte_branch_prediction.h>
2208bd1a17SNithin Dabilpuram #include <rte_common.h>
23ef853f1fSNithin Dabilpuram #include <rte_cycles.h>
2408bd1a17SNithin Dabilpuram #include <rte_eal.h>
2508bd1a17SNithin Dabilpuram #include <rte_ethdev.h>
26*a2bc0584SZhirun Yan #include <rte_graph_worker.h>
273087ec1cSNithin Dabilpuram #include <rte_launch.h>
28ef853f1fSNithin Dabilpuram #include <rte_lcore.h>
2908bd1a17SNithin Dabilpuram #include <rte_log.h>
307fc2cdf2SSunil Kumar Kori #include <rte_lpm6.h>
3108bd1a17SNithin Dabilpuram #include <rte_mempool.h>
323087ec1cSNithin Dabilpuram #include <rte_node_eth_api.h>
333087ec1cSNithin Dabilpuram #include <rte_node_ip4_api.h>
347fc2cdf2SSunil Kumar Kori #include <rte_node_ip6_api.h>
3508bd1a17SNithin Dabilpuram #include <rte_per_lcore.h>
3608bd1a17SNithin Dabilpuram #include <rte_string_fns.h>
3708bd1a17SNithin Dabilpuram #include <rte_vect.h>
3808bd1a17SNithin Dabilpuram 
3908bd1a17SNithin Dabilpuram #include <cmdline_parse.h>
4008bd1a17SNithin Dabilpuram #include <cmdline_parse_etheraddr.h>
4108bd1a17SNithin Dabilpuram 
4208bd1a17SNithin Dabilpuram /* Log type */
4308bd1a17SNithin Dabilpuram #define RTE_LOGTYPE_L3FWD_GRAPH RTE_LOGTYPE_USER1
4408bd1a17SNithin Dabilpuram 
4508bd1a17SNithin Dabilpuram /*
4608bd1a17SNithin Dabilpuram  * Configurable number of RX/TX ring descriptors
4708bd1a17SNithin Dabilpuram  */
484ed89049SDavid Marchand #define RX_DESC_DEFAULT 1024
494ed89049SDavid Marchand #define TX_DESC_DEFAULT 1024
5008bd1a17SNithin Dabilpuram 
5108bd1a17SNithin Dabilpuram #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
5208bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_PORT 128
5308bd1a17SNithin Dabilpuram 
5408bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_LCORE 16
5508bd1a17SNithin Dabilpuram 
5608bd1a17SNithin Dabilpuram #define MAX_LCORE_PARAMS 1024
5708bd1a17SNithin Dabilpuram 
5808bd1a17SNithin Dabilpuram #define NB_SOCKETS 8
5908bd1a17SNithin Dabilpuram 
60ef853f1fSNithin Dabilpuram /* Static global variables used within this file. */
614ed89049SDavid Marchand static uint16_t nb_rxd = RX_DESC_DEFAULT;
624ed89049SDavid Marchand static uint16_t nb_txd = TX_DESC_DEFAULT;
63ef853f1fSNithin Dabilpuram 
6408bd1a17SNithin Dabilpuram /**< Ports set in promiscuous mode off by default. */
6508bd1a17SNithin Dabilpuram static int promiscuous_on;
6608bd1a17SNithin Dabilpuram 
6708bd1a17SNithin Dabilpuram static int numa_on = 1;	  /**< NUMA is enabled by default. */
6808bd1a17SNithin Dabilpuram static int per_port_pool; /**< Use separate buffer pools per port; disabled */
6908bd1a17SNithin Dabilpuram 			  /**< by default */
7008bd1a17SNithin Dabilpuram 
7108bd1a17SNithin Dabilpuram static volatile bool force_quit;
7208bd1a17SNithin Dabilpuram 
7308bd1a17SNithin Dabilpuram /* Ethernet addresses of ports */
7408bd1a17SNithin Dabilpuram static uint64_t dest_eth_addr[RTE_MAX_ETHPORTS];
75ef853f1fSNithin Dabilpuram static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
7608bd1a17SNithin Dabilpuram xmm_t val_eth[RTE_MAX_ETHPORTS];
7708bd1a17SNithin Dabilpuram 
7808bd1a17SNithin Dabilpuram /* Mask of enabled ports */
7908bd1a17SNithin Dabilpuram static uint32_t enabled_port_mask;
8008bd1a17SNithin Dabilpuram 
819b72ea1fSAmit Prakash Shukla /* Pcap trace */
829b72ea1fSAmit Prakash Shukla static char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
839b72ea1fSAmit Prakash Shukla static uint64_t packet_to_capture;
849b72ea1fSAmit Prakash Shukla static int pcap_trace_enable;
859b72ea1fSAmit Prakash Shukla 
869b72ea1fSAmit Prakash Shukla 
8708bd1a17SNithin Dabilpuram struct lcore_rx_queue {
8808bd1a17SNithin Dabilpuram 	uint16_t port_id;
8908bd1a17SNithin Dabilpuram 	uint8_t queue_id;
903087ec1cSNithin Dabilpuram 	char node_name[RTE_NODE_NAMESIZE];
9108bd1a17SNithin Dabilpuram };
9208bd1a17SNithin Dabilpuram 
9308bd1a17SNithin Dabilpuram /* Lcore conf */
9408bd1a17SNithin Dabilpuram struct lcore_conf {
9508bd1a17SNithin Dabilpuram 	uint16_t n_rx_queue;
9608bd1a17SNithin Dabilpuram 	struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
973087ec1cSNithin Dabilpuram 
983087ec1cSNithin Dabilpuram 	struct rte_graph *graph;
993087ec1cSNithin Dabilpuram 	char name[RTE_GRAPH_NAMESIZE];
1003087ec1cSNithin Dabilpuram 	rte_graph_t graph_id;
10108bd1a17SNithin Dabilpuram } __rte_cache_aligned;
10208bd1a17SNithin Dabilpuram 
10308bd1a17SNithin Dabilpuram static struct lcore_conf lcore_conf[RTE_MAX_LCORE];
10408bd1a17SNithin Dabilpuram 
10508bd1a17SNithin Dabilpuram struct lcore_params {
10608bd1a17SNithin Dabilpuram 	uint16_t port_id;
10708bd1a17SNithin Dabilpuram 	uint8_t queue_id;
10808bd1a17SNithin Dabilpuram 	uint8_t lcore_id;
10908bd1a17SNithin Dabilpuram } __rte_cache_aligned;
11008bd1a17SNithin Dabilpuram 
11108bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];
11208bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array_default[] = {
11308bd1a17SNithin Dabilpuram 	{0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2},
11408bd1a17SNithin Dabilpuram 	{1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3},
11508bd1a17SNithin Dabilpuram };
11608bd1a17SNithin Dabilpuram 
11708bd1a17SNithin Dabilpuram static struct lcore_params *lcore_params = lcore_params_array_default;
11808bd1a17SNithin Dabilpuram static uint16_t nb_lcore_params = RTE_DIM(lcore_params_array_default);
11908bd1a17SNithin Dabilpuram 
12008bd1a17SNithin Dabilpuram static struct rte_eth_conf port_conf = {
12108bd1a17SNithin Dabilpuram 	.rxmode = {
122295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_RX_RSS,
12308bd1a17SNithin Dabilpuram 	},
12408bd1a17SNithin Dabilpuram 	.rx_adv_conf = {
12508bd1a17SNithin Dabilpuram 		.rss_conf = {
12608bd1a17SNithin Dabilpuram 				.rss_key = NULL,
127295968d1SFerruh Yigit 				.rss_hf = RTE_ETH_RSS_IP,
12808bd1a17SNithin Dabilpuram 		},
12908bd1a17SNithin Dabilpuram 	},
13008bd1a17SNithin Dabilpuram 	.txmode = {
131295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_TX_NONE,
13208bd1a17SNithin Dabilpuram 	},
13308bd1a17SNithin Dabilpuram };
13408bd1a17SNithin Dabilpuram 
1351bb4a528SFerruh Yigit static uint32_t max_pkt_len;
1361bb4a528SFerruh Yigit 
137ef853f1fSNithin Dabilpuram static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS];
138ef853f1fSNithin Dabilpuram 
1393087ec1cSNithin Dabilpuram static struct rte_node_ethdev_config ethdev_conf[RTE_MAX_ETHPORTS];
1403087ec1cSNithin Dabilpuram 
1413087ec1cSNithin Dabilpuram struct ipv4_l3fwd_lpm_route {
1423087ec1cSNithin Dabilpuram 	uint32_t ip;
1433087ec1cSNithin Dabilpuram 	uint8_t depth;
1443087ec1cSNithin Dabilpuram 	uint8_t if_out;
1453087ec1cSNithin Dabilpuram };
1463087ec1cSNithin Dabilpuram 
1477fc2cdf2SSunil Kumar Kori struct ipv6_l3fwd_lpm_route {
1487fc2cdf2SSunil Kumar Kori 	uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE];
1497fc2cdf2SSunil Kumar Kori 	uint8_t depth;
1507fc2cdf2SSunil Kumar Kori 	uint8_t if_out;
1517fc2cdf2SSunil Kumar Kori };
1527fc2cdf2SSunil Kumar Kori 
1533087ec1cSNithin Dabilpuram #define IPV4_L3FWD_LPM_NUM_ROUTES                                              \
1543087ec1cSNithin Dabilpuram 	(sizeof(ipv4_l3fwd_lpm_route_array) /                                  \
1553087ec1cSNithin Dabilpuram 	 sizeof(ipv4_l3fwd_lpm_route_array[0]))
1563087ec1cSNithin Dabilpuram /* 198.18.0.0/16 are set aside for RFC2544 benchmarking. */
1573087ec1cSNithin Dabilpuram static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
1583087ec1cSNithin Dabilpuram 	{RTE_IPV4(198, 18, 0, 0), 24, 0}, {RTE_IPV4(198, 18, 1, 0), 24, 1},
1593087ec1cSNithin Dabilpuram 	{RTE_IPV4(198, 18, 2, 0), 24, 2}, {RTE_IPV4(198, 18, 3, 0), 24, 3},
1603087ec1cSNithin Dabilpuram 	{RTE_IPV4(198, 18, 4, 0), 24, 4}, {RTE_IPV4(198, 18, 5, 0), 24, 5},
1613087ec1cSNithin Dabilpuram 	{RTE_IPV4(198, 18, 6, 0), 24, 6}, {RTE_IPV4(198, 18, 7, 0), 24, 7},
1623087ec1cSNithin Dabilpuram };
1633087ec1cSNithin Dabilpuram 
1647fc2cdf2SSunil Kumar Kori #define IPV6_L3FWD_LPM_NUM_ROUTES                                              \
1657fc2cdf2SSunil Kumar Kori 	(sizeof(ipv6_l3fwd_lpm_route_array) /                                  \
1667fc2cdf2SSunil Kumar Kori 	 sizeof(ipv6_l3fwd_lpm_route_array[0]))
1677fc2cdf2SSunil Kumar Kori static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
1687fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1697fc2cdf2SSunil Kumar Kori 	0x00}, 48, 0},
1707fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1717fc2cdf2SSunil Kumar Kori 	0x01}, 48, 1},
1727fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1737fc2cdf2SSunil Kumar Kori 	0x02}, 48, 2},
1747fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1757fc2cdf2SSunil Kumar Kori 	0x03}, 48, 3},
1767fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1777fc2cdf2SSunil Kumar Kori 	0x04}, 48, 4},
1787fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1797fc2cdf2SSunil Kumar Kori 	0x05}, 48, 5},
1807fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1817fc2cdf2SSunil Kumar Kori 	0x06}, 48, 6},
1827fc2cdf2SSunil Kumar Kori 	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1837fc2cdf2SSunil Kumar Kori 	0x02}, 48, 7},
1847fc2cdf2SSunil Kumar Kori };
1857fc2cdf2SSunil Kumar Kori 
18608bd1a17SNithin Dabilpuram static int
18708bd1a17SNithin Dabilpuram check_lcore_params(void)
18808bd1a17SNithin Dabilpuram {
18908bd1a17SNithin Dabilpuram 	uint8_t queue, lcore;
19008bd1a17SNithin Dabilpuram 	int socketid;
19108bd1a17SNithin Dabilpuram 	uint16_t i;
19208bd1a17SNithin Dabilpuram 
19308bd1a17SNithin Dabilpuram 	for (i = 0; i < nb_lcore_params; ++i) {
19408bd1a17SNithin Dabilpuram 		queue = lcore_params[i].queue_id;
19508bd1a17SNithin Dabilpuram 		if (queue >= MAX_RX_QUEUE_PER_PORT) {
19608bd1a17SNithin Dabilpuram 			printf("Invalid queue number: %hhu\n", queue);
19708bd1a17SNithin Dabilpuram 			return -1;
19808bd1a17SNithin Dabilpuram 		}
19908bd1a17SNithin Dabilpuram 		lcore = lcore_params[i].lcore_id;
20008bd1a17SNithin Dabilpuram 		if (!rte_lcore_is_enabled(lcore)) {
20108bd1a17SNithin Dabilpuram 			printf("Error: lcore %hhu is not enabled in lcore mask\n",
20208bd1a17SNithin Dabilpuram 			       lcore);
20308bd1a17SNithin Dabilpuram 			return -1;
20408bd1a17SNithin Dabilpuram 		}
20508bd1a17SNithin Dabilpuram 
206cb056611SStephen Hemminger 		if (lcore == rte_get_main_lcore()) {
207cb056611SStephen Hemminger 			printf("Error: lcore %u is main lcore\n", lcore);
20808bd1a17SNithin Dabilpuram 			return -1;
20908bd1a17SNithin Dabilpuram 		}
21008bd1a17SNithin Dabilpuram 		socketid = rte_lcore_to_socket_id(lcore);
21108bd1a17SNithin Dabilpuram 		if ((socketid != 0) && (numa_on == 0)) {
21208bd1a17SNithin Dabilpuram 			printf("Warning: lcore %hhu is on socket %d with numa off\n",
21308bd1a17SNithin Dabilpuram 			       lcore, socketid);
21408bd1a17SNithin Dabilpuram 		}
21508bd1a17SNithin Dabilpuram 	}
21608bd1a17SNithin Dabilpuram 
21708bd1a17SNithin Dabilpuram 	return 0;
21808bd1a17SNithin Dabilpuram }
21908bd1a17SNithin Dabilpuram 
22008bd1a17SNithin Dabilpuram static int
22108bd1a17SNithin Dabilpuram check_port_config(void)
22208bd1a17SNithin Dabilpuram {
22308bd1a17SNithin Dabilpuram 	uint16_t portid;
22408bd1a17SNithin Dabilpuram 	uint16_t i;
22508bd1a17SNithin Dabilpuram 
22608bd1a17SNithin Dabilpuram 	for (i = 0; i < nb_lcore_params; ++i) {
22708bd1a17SNithin Dabilpuram 		portid = lcore_params[i].port_id;
22808bd1a17SNithin Dabilpuram 		if ((enabled_port_mask & (1 << portid)) == 0) {
22908bd1a17SNithin Dabilpuram 			printf("Port %u is not enabled in port mask\n", portid);
23008bd1a17SNithin Dabilpuram 			return -1;
23108bd1a17SNithin Dabilpuram 		}
23208bd1a17SNithin Dabilpuram 		if (!rte_eth_dev_is_valid_port(portid)) {
23308bd1a17SNithin Dabilpuram 			printf("Port %u is not present on the board\n", portid);
23408bd1a17SNithin Dabilpuram 			return -1;
23508bd1a17SNithin Dabilpuram 		}
23608bd1a17SNithin Dabilpuram 	}
23708bd1a17SNithin Dabilpuram 
23808bd1a17SNithin Dabilpuram 	return 0;
23908bd1a17SNithin Dabilpuram }
24008bd1a17SNithin Dabilpuram 
241ef853f1fSNithin Dabilpuram static uint8_t
242ef853f1fSNithin Dabilpuram get_port_n_rx_queues(const uint16_t port)
243ef853f1fSNithin Dabilpuram {
244ef853f1fSNithin Dabilpuram 	int queue = -1;
245ef853f1fSNithin Dabilpuram 	uint16_t i;
246ef853f1fSNithin Dabilpuram 
247ef853f1fSNithin Dabilpuram 	for (i = 0; i < nb_lcore_params; ++i) {
248ef853f1fSNithin Dabilpuram 		if (lcore_params[i].port_id == port) {
249ef853f1fSNithin Dabilpuram 			if (lcore_params[i].queue_id == queue + 1)
250ef853f1fSNithin Dabilpuram 				queue = lcore_params[i].queue_id;
251ef853f1fSNithin Dabilpuram 			else
252ef853f1fSNithin Dabilpuram 				rte_exit(EXIT_FAILURE,
253ef853f1fSNithin Dabilpuram 					 "Queue ids of the port %d must be"
254ef853f1fSNithin Dabilpuram 					 " in sequence and must start with 0\n",
255ef853f1fSNithin Dabilpuram 					 lcore_params[i].port_id);
256ef853f1fSNithin Dabilpuram 		}
257ef853f1fSNithin Dabilpuram 	}
258ef853f1fSNithin Dabilpuram 
259ef853f1fSNithin Dabilpuram 	return (uint8_t)(++queue);
260ef853f1fSNithin Dabilpuram }
261ef853f1fSNithin Dabilpuram 
26208bd1a17SNithin Dabilpuram static int
26308bd1a17SNithin Dabilpuram init_lcore_rx_queues(void)
26408bd1a17SNithin Dabilpuram {
26508bd1a17SNithin Dabilpuram 	uint16_t i, nb_rx_queue;
26608bd1a17SNithin Dabilpuram 	uint8_t lcore;
26708bd1a17SNithin Dabilpuram 
26808bd1a17SNithin Dabilpuram 	for (i = 0; i < nb_lcore_params; ++i) {
26908bd1a17SNithin Dabilpuram 		lcore = lcore_params[i].lcore_id;
27008bd1a17SNithin Dabilpuram 		nb_rx_queue = lcore_conf[lcore].n_rx_queue;
27108bd1a17SNithin Dabilpuram 		if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) {
27208bd1a17SNithin Dabilpuram 			printf("Error: too many queues (%u) for lcore: %u\n",
27308bd1a17SNithin Dabilpuram 			       (unsigned int)nb_rx_queue + 1,
27408bd1a17SNithin Dabilpuram 			       (unsigned int)lcore);
27508bd1a17SNithin Dabilpuram 			return -1;
27608bd1a17SNithin Dabilpuram 		}
27708bd1a17SNithin Dabilpuram 
27808bd1a17SNithin Dabilpuram 		lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id =
27908bd1a17SNithin Dabilpuram 			lcore_params[i].port_id;
28008bd1a17SNithin Dabilpuram 		lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id =
28108bd1a17SNithin Dabilpuram 			lcore_params[i].queue_id;
28208bd1a17SNithin Dabilpuram 		lcore_conf[lcore].n_rx_queue++;
28308bd1a17SNithin Dabilpuram 	}
28408bd1a17SNithin Dabilpuram 
28508bd1a17SNithin Dabilpuram 	return 0;
28608bd1a17SNithin Dabilpuram }
28708bd1a17SNithin Dabilpuram 
28808bd1a17SNithin Dabilpuram /* Display usage */
28908bd1a17SNithin Dabilpuram static void
29008bd1a17SNithin Dabilpuram print_usage(const char *prgname)
29108bd1a17SNithin Dabilpuram {
29208bd1a17SNithin Dabilpuram 	fprintf(stderr,
29308bd1a17SNithin Dabilpuram 		"%s [EAL options] --"
29408bd1a17SNithin Dabilpuram 		" -p PORTMASK"
29508bd1a17SNithin Dabilpuram 		" [-P]"
29608bd1a17SNithin Dabilpuram 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
29708bd1a17SNithin Dabilpuram 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
2981bb4a528SFerruh Yigit 		" [--max-pkt-len PKTLEN]"
29908bd1a17SNithin Dabilpuram 		" [--no-numa]"
3009b72ea1fSAmit Prakash Shukla 		" [--per-port-pool]"
3019b72ea1fSAmit Prakash Shukla 		" [--num-pkt-cap]\n\n"
30208bd1a17SNithin Dabilpuram 
30308bd1a17SNithin Dabilpuram 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
30408bd1a17SNithin Dabilpuram 		"  -P : Enable promiscuous mode\n"
30508bd1a17SNithin Dabilpuram 		"  --config (port,queue,lcore): Rx queue configuration\n"
30608bd1a17SNithin Dabilpuram 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for "
30708bd1a17SNithin Dabilpuram 		"port X\n"
3081bb4a528SFerruh Yigit 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
30908bd1a17SNithin Dabilpuram 		"  --no-numa: Disable numa awareness\n"
3109b72ea1fSAmit Prakash Shukla 		"  --per-port-pool: Use separate buffer pool per port\n"
3119b72ea1fSAmit Prakash Shukla 		"  --pcap-enable: Enables pcap capture\n"
3129b72ea1fSAmit Prakash Shukla 		"  --pcap-num-cap NUMPKT: Number of packets to capture\n"
3139b72ea1fSAmit Prakash Shukla 		"  --pcap-file-name NAME: Pcap file name\n\n",
31408bd1a17SNithin Dabilpuram 		prgname);
31508bd1a17SNithin Dabilpuram }
31608bd1a17SNithin Dabilpuram 
3179b72ea1fSAmit Prakash Shukla static uint64_t
3189b72ea1fSAmit Prakash Shukla parse_num_pkt_cap(const char *num_pkt_cap)
3199b72ea1fSAmit Prakash Shukla {
3209b72ea1fSAmit Prakash Shukla 	uint64_t num_pkt;
3219b72ea1fSAmit Prakash Shukla 	char *end = NULL;
3229b72ea1fSAmit Prakash Shukla 
3239b72ea1fSAmit Prakash Shukla 	/* Parse decimal string */
3249b72ea1fSAmit Prakash Shukla 	num_pkt = strtoull(num_pkt_cap, &end, 10);
3259b72ea1fSAmit Prakash Shukla 	if ((num_pkt_cap[0] == '\0') || (end == NULL) || (*end != '\0'))
3269b72ea1fSAmit Prakash Shukla 		return 0;
3279b72ea1fSAmit Prakash Shukla 
3289b72ea1fSAmit Prakash Shukla 	if (num_pkt == 0)
3299b72ea1fSAmit Prakash Shukla 		return 0;
3309b72ea1fSAmit Prakash Shukla 
3319b72ea1fSAmit Prakash Shukla 	return num_pkt;
3329b72ea1fSAmit Prakash Shukla }
3339b72ea1fSAmit Prakash Shukla 
33408bd1a17SNithin Dabilpuram static int
33508bd1a17SNithin Dabilpuram parse_max_pkt_len(const char *pktlen)
33608bd1a17SNithin Dabilpuram {
33708bd1a17SNithin Dabilpuram 	unsigned long len;
33808bd1a17SNithin Dabilpuram 	char *end = NULL;
33908bd1a17SNithin Dabilpuram 
34008bd1a17SNithin Dabilpuram 	/* Parse decimal string */
34108bd1a17SNithin Dabilpuram 	len = strtoul(pktlen, &end, 10);
34208bd1a17SNithin Dabilpuram 	if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0'))
34308bd1a17SNithin Dabilpuram 		return -1;
34408bd1a17SNithin Dabilpuram 
34508bd1a17SNithin Dabilpuram 	if (len == 0)
34608bd1a17SNithin Dabilpuram 		return -1;
34708bd1a17SNithin Dabilpuram 
34808bd1a17SNithin Dabilpuram 	return len;
34908bd1a17SNithin Dabilpuram }
35008bd1a17SNithin Dabilpuram 
35108bd1a17SNithin Dabilpuram static int
35208bd1a17SNithin Dabilpuram parse_portmask(const char *portmask)
35308bd1a17SNithin Dabilpuram {
35408bd1a17SNithin Dabilpuram 	char *end = NULL;
35508bd1a17SNithin Dabilpuram 	unsigned long pm;
35608bd1a17SNithin Dabilpuram 
35708bd1a17SNithin Dabilpuram 	/* Parse hexadecimal string */
35808bd1a17SNithin Dabilpuram 	pm = strtoul(portmask, &end, 16);
35908bd1a17SNithin Dabilpuram 	if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
360ce6b8c31SSarosh Arif 		return 0;
36108bd1a17SNithin Dabilpuram 
36208bd1a17SNithin Dabilpuram 	return pm;
36308bd1a17SNithin Dabilpuram }
36408bd1a17SNithin Dabilpuram 
36508bd1a17SNithin Dabilpuram static int
36608bd1a17SNithin Dabilpuram parse_config(const char *q_arg)
36708bd1a17SNithin Dabilpuram {
36808bd1a17SNithin Dabilpuram 	enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD };
36908bd1a17SNithin Dabilpuram 	unsigned long int_fld[_NUM_FLD];
37008bd1a17SNithin Dabilpuram 	const char *p, *p0 = q_arg;
37108bd1a17SNithin Dabilpuram 	char *str_fld[_NUM_FLD];
37208bd1a17SNithin Dabilpuram 	uint32_t size;
37308bd1a17SNithin Dabilpuram 	char s[256];
37408bd1a17SNithin Dabilpuram 	char *end;
37508bd1a17SNithin Dabilpuram 	int i;
37608bd1a17SNithin Dabilpuram 
37708bd1a17SNithin Dabilpuram 	nb_lcore_params = 0;
37808bd1a17SNithin Dabilpuram 
37908bd1a17SNithin Dabilpuram 	while ((p = strchr(p0, '(')) != NULL) {
38008bd1a17SNithin Dabilpuram 		++p;
38108bd1a17SNithin Dabilpuram 		p0 = strchr(p, ')');
38208bd1a17SNithin Dabilpuram 		if (p0 == NULL)
38308bd1a17SNithin Dabilpuram 			return -1;
38408bd1a17SNithin Dabilpuram 
38508bd1a17SNithin Dabilpuram 		size = p0 - p;
38608bd1a17SNithin Dabilpuram 		if (size >= sizeof(s))
38708bd1a17SNithin Dabilpuram 			return -1;
38808bd1a17SNithin Dabilpuram 
38908bd1a17SNithin Dabilpuram 		memcpy(s, p, size);
39008bd1a17SNithin Dabilpuram 		s[size] = '\0';
39108bd1a17SNithin Dabilpuram 		if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') !=
39208bd1a17SNithin Dabilpuram 		    _NUM_FLD)
39308bd1a17SNithin Dabilpuram 			return -1;
39408bd1a17SNithin Dabilpuram 		for (i = 0; i < _NUM_FLD; i++) {
39508bd1a17SNithin Dabilpuram 			errno = 0;
39608bd1a17SNithin Dabilpuram 			int_fld[i] = strtoul(str_fld[i], &end, 0);
39708bd1a17SNithin Dabilpuram 			if (errno != 0 || end == str_fld[i])
39808bd1a17SNithin Dabilpuram 				return -1;
39908bd1a17SNithin Dabilpuram 		}
40008bd1a17SNithin Dabilpuram 
40108bd1a17SNithin Dabilpuram 		if (nb_lcore_params >= MAX_LCORE_PARAMS) {
40208bd1a17SNithin Dabilpuram 			printf("Exceeded max number of lcore params: %hu\n",
40308bd1a17SNithin Dabilpuram 			       nb_lcore_params);
40408bd1a17SNithin Dabilpuram 			return -1;
40508bd1a17SNithin Dabilpuram 		}
40608bd1a17SNithin Dabilpuram 
40708bd1a17SNithin Dabilpuram 		if (int_fld[FLD_PORT] >= RTE_MAX_ETHPORTS ||
40808bd1a17SNithin Dabilpuram 		    int_fld[FLD_LCORE] >= RTE_MAX_LCORE) {
40908bd1a17SNithin Dabilpuram 			printf("Invalid port/lcore id\n");
41008bd1a17SNithin Dabilpuram 			return -1;
41108bd1a17SNithin Dabilpuram 		}
41208bd1a17SNithin Dabilpuram 
41308bd1a17SNithin Dabilpuram 		lcore_params_array[nb_lcore_params].port_id =
41408bd1a17SNithin Dabilpuram 			(uint8_t)int_fld[FLD_PORT];
41508bd1a17SNithin Dabilpuram 		lcore_params_array[nb_lcore_params].queue_id =
41608bd1a17SNithin Dabilpuram 			(uint8_t)int_fld[FLD_QUEUE];
41708bd1a17SNithin Dabilpuram 		lcore_params_array[nb_lcore_params].lcore_id =
41808bd1a17SNithin Dabilpuram 			(uint8_t)int_fld[FLD_LCORE];
41908bd1a17SNithin Dabilpuram 		++nb_lcore_params;
42008bd1a17SNithin Dabilpuram 	}
42108bd1a17SNithin Dabilpuram 	lcore_params = lcore_params_array;
42208bd1a17SNithin Dabilpuram 
42308bd1a17SNithin Dabilpuram 	return 0;
42408bd1a17SNithin Dabilpuram }
42508bd1a17SNithin Dabilpuram 
42608bd1a17SNithin Dabilpuram static void
42708bd1a17SNithin Dabilpuram parse_eth_dest(const char *optarg)
42808bd1a17SNithin Dabilpuram {
42908bd1a17SNithin Dabilpuram 	uint8_t c, *dest, peer_addr[6];
43008bd1a17SNithin Dabilpuram 	uint16_t portid;
43108bd1a17SNithin Dabilpuram 	char *port_end;
43208bd1a17SNithin Dabilpuram 
43308bd1a17SNithin Dabilpuram 	errno = 0;
43408bd1a17SNithin Dabilpuram 	portid = strtoul(optarg, &port_end, 10);
43508bd1a17SNithin Dabilpuram 	if (errno != 0 || port_end == optarg || *port_end++ != ',')
43608bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "Invalid eth-dest: %s", optarg);
43708bd1a17SNithin Dabilpuram 	if (portid >= RTE_MAX_ETHPORTS)
43808bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE,
43908bd1a17SNithin Dabilpuram 			 "eth-dest: port %d >= RTE_MAX_ETHPORTS(%d)\n", portid,
44008bd1a17SNithin Dabilpuram 			 RTE_MAX_ETHPORTS);
44108bd1a17SNithin Dabilpuram 
44208bd1a17SNithin Dabilpuram 	if (cmdline_parse_etheraddr(NULL, port_end, &peer_addr,
44308bd1a17SNithin Dabilpuram 				    sizeof(peer_addr)) < 0)
44408bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "Invalid ethernet address: %s\n",
44508bd1a17SNithin Dabilpuram 			 port_end);
44608bd1a17SNithin Dabilpuram 	dest = (uint8_t *)&dest_eth_addr[portid];
44708bd1a17SNithin Dabilpuram 	for (c = 0; c < 6; c++)
44808bd1a17SNithin Dabilpuram 		dest[c] = peer_addr[c];
44908bd1a17SNithin Dabilpuram 	*(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
45008bd1a17SNithin Dabilpuram }
45108bd1a17SNithin Dabilpuram 
45208bd1a17SNithin Dabilpuram #define MAX_JUMBO_PKT_LEN  9600
45308bd1a17SNithin Dabilpuram #define MEMPOOL_CACHE_SIZE 256
45408bd1a17SNithin Dabilpuram 
45508bd1a17SNithin Dabilpuram static const char short_options[] = "p:" /* portmask */
45608bd1a17SNithin Dabilpuram 				    "P"	 /* promiscuous */
45708bd1a17SNithin Dabilpuram 	;
45808bd1a17SNithin Dabilpuram 
45908bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_CONFIG	   "config"
46008bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_ETH_DEST	   "eth-dest"
46108bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_NO_NUMA	   "no-numa"
4621bb4a528SFerruh Yigit #define CMD_LINE_OPT_MAX_PKT_LEN   "max-pkt-len"
46308bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
4649b72ea1fSAmit Prakash Shukla #define CMD_LINE_OPT_PCAP_ENABLE   "pcap-enable"
4659b72ea1fSAmit Prakash Shukla #define CMD_LINE_OPT_NUM_PKT_CAP   "pcap-num-cap"
4669b72ea1fSAmit Prakash Shukla #define CMD_LINE_OPT_PCAP_FILENAME "pcap-file-name"
46708bd1a17SNithin Dabilpuram enum {
46808bd1a17SNithin Dabilpuram 	/* Long options mapped to a short option */
46908bd1a17SNithin Dabilpuram 
47008bd1a17SNithin Dabilpuram 	/* First long only option value must be >= 256, so that we won't
47108bd1a17SNithin Dabilpuram 	 * conflict with short options
47208bd1a17SNithin Dabilpuram 	 */
47308bd1a17SNithin Dabilpuram 	CMD_LINE_OPT_MIN_NUM = 256,
47408bd1a17SNithin Dabilpuram 	CMD_LINE_OPT_CONFIG_NUM,
47508bd1a17SNithin Dabilpuram 	CMD_LINE_OPT_ETH_DEST_NUM,
47608bd1a17SNithin Dabilpuram 	CMD_LINE_OPT_NO_NUMA_NUM,
4771bb4a528SFerruh Yigit 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
47808bd1a17SNithin Dabilpuram 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
4799b72ea1fSAmit Prakash Shukla 	CMD_LINE_OPT_PARSE_PCAP_ENABLE,
4809b72ea1fSAmit Prakash Shukla 	CMD_LINE_OPT_PARSE_NUM_PKT_CAP,
4819b72ea1fSAmit Prakash Shukla 	CMD_LINE_OPT_PCAP_FILENAME_CAP,
48208bd1a17SNithin Dabilpuram };
48308bd1a17SNithin Dabilpuram 
48408bd1a17SNithin Dabilpuram static const struct option lgopts[] = {
48508bd1a17SNithin Dabilpuram 	{CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM},
48608bd1a17SNithin Dabilpuram 	{CMD_LINE_OPT_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM},
48708bd1a17SNithin Dabilpuram 	{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
4881bb4a528SFerruh Yigit 	{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, CMD_LINE_OPT_MAX_PKT_LEN_NUM},
48908bd1a17SNithin Dabilpuram 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
4909b72ea1fSAmit Prakash Shukla 	{CMD_LINE_OPT_PCAP_ENABLE, 0, 0, CMD_LINE_OPT_PARSE_PCAP_ENABLE},
4919b72ea1fSAmit Prakash Shukla 	{CMD_LINE_OPT_NUM_PKT_CAP, 1, 0, CMD_LINE_OPT_PARSE_NUM_PKT_CAP},
4929b72ea1fSAmit Prakash Shukla 	{CMD_LINE_OPT_PCAP_FILENAME, 1, 0, CMD_LINE_OPT_PCAP_FILENAME_CAP},
49308bd1a17SNithin Dabilpuram 	{NULL, 0, 0, 0},
49408bd1a17SNithin Dabilpuram };
49508bd1a17SNithin Dabilpuram 
49608bd1a17SNithin Dabilpuram /*
49708bd1a17SNithin Dabilpuram  * This expression is used to calculate the number of mbufs needed
49808bd1a17SNithin Dabilpuram  * depending on user input, taking  into account memory for rx and
49908bd1a17SNithin Dabilpuram  * tx hardware rings, cache per lcore and mtable per port per lcore.
50008bd1a17SNithin Dabilpuram  * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum
50108bd1a17SNithin Dabilpuram  * value of 8192
50208bd1a17SNithin Dabilpuram  */
50308bd1a17SNithin Dabilpuram #define NB_MBUF(nports)                                                        \
50408bd1a17SNithin Dabilpuram 	RTE_MAX((nports * nb_rx_queue * nb_rxd +                               \
50508bd1a17SNithin Dabilpuram 		 nports * nb_lcores * RTE_GRAPH_BURST_SIZE +                   \
50608bd1a17SNithin Dabilpuram 		 nports * n_tx_queue * nb_txd +                                \
50708bd1a17SNithin Dabilpuram 		 nb_lcores * MEMPOOL_CACHE_SIZE), 8192u)
50808bd1a17SNithin Dabilpuram 
50908bd1a17SNithin Dabilpuram /* Parse the argument given in the command line of the application */
51008bd1a17SNithin Dabilpuram static int
51108bd1a17SNithin Dabilpuram parse_args(int argc, char **argv)
51208bd1a17SNithin Dabilpuram {
51308bd1a17SNithin Dabilpuram 	char *prgname = argv[0];
51408bd1a17SNithin Dabilpuram 	int option_index;
51508bd1a17SNithin Dabilpuram 	char **argvopt;
51608bd1a17SNithin Dabilpuram 	int opt, ret;
51708bd1a17SNithin Dabilpuram 
51808bd1a17SNithin Dabilpuram 	argvopt = argv;
51908bd1a17SNithin Dabilpuram 
52008bd1a17SNithin Dabilpuram 	/* Error or normal output strings. */
52108bd1a17SNithin Dabilpuram 	while ((opt = getopt_long(argc, argvopt, short_options, lgopts,
52208bd1a17SNithin Dabilpuram 				  &option_index)) != EOF) {
52308bd1a17SNithin Dabilpuram 
52408bd1a17SNithin Dabilpuram 		switch (opt) {
52508bd1a17SNithin Dabilpuram 		/* Portmask */
52608bd1a17SNithin Dabilpuram 		case 'p':
52708bd1a17SNithin Dabilpuram 			enabled_port_mask = parse_portmask(optarg);
52808bd1a17SNithin Dabilpuram 			if (enabled_port_mask == 0) {
52908bd1a17SNithin Dabilpuram 				fprintf(stderr, "Invalid portmask\n");
53008bd1a17SNithin Dabilpuram 				print_usage(prgname);
53108bd1a17SNithin Dabilpuram 				return -1;
53208bd1a17SNithin Dabilpuram 			}
53308bd1a17SNithin Dabilpuram 			break;
53408bd1a17SNithin Dabilpuram 
53508bd1a17SNithin Dabilpuram 		case 'P':
53608bd1a17SNithin Dabilpuram 			promiscuous_on = 1;
53708bd1a17SNithin Dabilpuram 			break;
53808bd1a17SNithin Dabilpuram 
53908bd1a17SNithin Dabilpuram 		/* Long options */
54008bd1a17SNithin Dabilpuram 		case CMD_LINE_OPT_CONFIG_NUM:
54108bd1a17SNithin Dabilpuram 			ret = parse_config(optarg);
54208bd1a17SNithin Dabilpuram 			if (ret) {
54308bd1a17SNithin Dabilpuram 				fprintf(stderr, "Invalid config\n");
54408bd1a17SNithin Dabilpuram 				print_usage(prgname);
54508bd1a17SNithin Dabilpuram 				return -1;
54608bd1a17SNithin Dabilpuram 			}
54708bd1a17SNithin Dabilpuram 			break;
54808bd1a17SNithin Dabilpuram 
54908bd1a17SNithin Dabilpuram 		case CMD_LINE_OPT_ETH_DEST_NUM:
55008bd1a17SNithin Dabilpuram 			parse_eth_dest(optarg);
55108bd1a17SNithin Dabilpuram 			break;
55208bd1a17SNithin Dabilpuram 
55308bd1a17SNithin Dabilpuram 		case CMD_LINE_OPT_NO_NUMA_NUM:
55408bd1a17SNithin Dabilpuram 			numa_on = 0;
55508bd1a17SNithin Dabilpuram 			break;
55608bd1a17SNithin Dabilpuram 
5571bb4a528SFerruh Yigit 		case CMD_LINE_OPT_MAX_PKT_LEN_NUM: {
5581bb4a528SFerruh Yigit 			max_pkt_len = parse_max_pkt_len(optarg);
55908bd1a17SNithin Dabilpuram 			break;
56008bd1a17SNithin Dabilpuram 		}
56108bd1a17SNithin Dabilpuram 
56208bd1a17SNithin Dabilpuram 		case CMD_LINE_OPT_PARSE_PER_PORT_POOL:
56308bd1a17SNithin Dabilpuram 			printf("Per port buffer pool is enabled\n");
56408bd1a17SNithin Dabilpuram 			per_port_pool = 1;
56508bd1a17SNithin Dabilpuram 			break;
56608bd1a17SNithin Dabilpuram 
5679b72ea1fSAmit Prakash Shukla 		case CMD_LINE_OPT_PARSE_PCAP_ENABLE:
5689b72ea1fSAmit Prakash Shukla 			printf("Packet capture enabled\n");
5699b72ea1fSAmit Prakash Shukla 			pcap_trace_enable = 1;
5709b72ea1fSAmit Prakash Shukla 			break;
5719b72ea1fSAmit Prakash Shukla 
5729b72ea1fSAmit Prakash Shukla 		case CMD_LINE_OPT_PARSE_NUM_PKT_CAP:
5739b72ea1fSAmit Prakash Shukla 			packet_to_capture = parse_num_pkt_cap(optarg);
5749b72ea1fSAmit Prakash Shukla 			printf("Number of packets to capture: %"PRIu64"\n",
5759b72ea1fSAmit Prakash Shukla 			       packet_to_capture);
5769b72ea1fSAmit Prakash Shukla 			break;
5779b72ea1fSAmit Prakash Shukla 
5789b72ea1fSAmit Prakash Shukla 		case CMD_LINE_OPT_PCAP_FILENAME_CAP:
5799b72ea1fSAmit Prakash Shukla 			rte_strlcpy(pcap_filename, optarg,
5809b72ea1fSAmit Prakash Shukla 				    sizeof(pcap_filename));
5819b72ea1fSAmit Prakash Shukla 			printf("Pcap file name: %s\n", pcap_filename);
5829b72ea1fSAmit Prakash Shukla 			break;
5839b72ea1fSAmit Prakash Shukla 
58408bd1a17SNithin Dabilpuram 		default:
58508bd1a17SNithin Dabilpuram 			print_usage(prgname);
58608bd1a17SNithin Dabilpuram 			return -1;
58708bd1a17SNithin Dabilpuram 		}
58808bd1a17SNithin Dabilpuram 	}
58908bd1a17SNithin Dabilpuram 
59008bd1a17SNithin Dabilpuram 	if (optind >= 0)
59108bd1a17SNithin Dabilpuram 		argv[optind - 1] = prgname;
59208bd1a17SNithin Dabilpuram 	ret = optind - 1;
59308bd1a17SNithin Dabilpuram 	optind = 1; /* Reset getopt lib */
59408bd1a17SNithin Dabilpuram 
59508bd1a17SNithin Dabilpuram 	return ret;
59608bd1a17SNithin Dabilpuram }
59708bd1a17SNithin Dabilpuram 
59808bd1a17SNithin Dabilpuram static void
599ef853f1fSNithin Dabilpuram print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
600ef853f1fSNithin Dabilpuram {
601ef853f1fSNithin Dabilpuram 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
602ef853f1fSNithin Dabilpuram 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
603ef853f1fSNithin Dabilpuram 	printf("%s%s", name, buf);
604ef853f1fSNithin Dabilpuram }
605ef853f1fSNithin Dabilpuram 
606ef853f1fSNithin Dabilpuram static int
607ef853f1fSNithin Dabilpuram init_mem(uint16_t portid, uint32_t nb_mbuf)
608ef853f1fSNithin Dabilpuram {
609ef853f1fSNithin Dabilpuram 	uint32_t lcore_id;
610ef853f1fSNithin Dabilpuram 	int socketid;
611ef853f1fSNithin Dabilpuram 	char s[64];
612ef853f1fSNithin Dabilpuram 
613ef853f1fSNithin Dabilpuram 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
614ef853f1fSNithin Dabilpuram 		if (rte_lcore_is_enabled(lcore_id) == 0)
615ef853f1fSNithin Dabilpuram 			continue;
616ef853f1fSNithin Dabilpuram 
617ef853f1fSNithin Dabilpuram 		if (numa_on)
618ef853f1fSNithin Dabilpuram 			socketid = rte_lcore_to_socket_id(lcore_id);
619ef853f1fSNithin Dabilpuram 		else
620ef853f1fSNithin Dabilpuram 			socketid = 0;
621ef853f1fSNithin Dabilpuram 
622ef853f1fSNithin Dabilpuram 		if (socketid >= NB_SOCKETS) {
623ef853f1fSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
624ef853f1fSNithin Dabilpuram 				 "Socket %d of lcore %u is out of range %d\n",
625ef853f1fSNithin Dabilpuram 				 socketid, lcore_id, NB_SOCKETS);
626ef853f1fSNithin Dabilpuram 		}
627ef853f1fSNithin Dabilpuram 
628ef853f1fSNithin Dabilpuram 		if (pktmbuf_pool[portid][socketid] == NULL) {
629ef853f1fSNithin Dabilpuram 			snprintf(s, sizeof(s), "mbuf_pool_%d:%d", portid,
630ef853f1fSNithin Dabilpuram 				 socketid);
631ef853f1fSNithin Dabilpuram 			/* Create a pool with priv size of a cacheline */
632ef853f1fSNithin Dabilpuram 			pktmbuf_pool[portid][socketid] =
633ef853f1fSNithin Dabilpuram 				rte_pktmbuf_pool_create(
634ef853f1fSNithin Dabilpuram 					s, nb_mbuf, MEMPOOL_CACHE_SIZE,
635ef853f1fSNithin Dabilpuram 					RTE_CACHE_LINE_SIZE,
636ef853f1fSNithin Dabilpuram 					RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
637ef853f1fSNithin Dabilpuram 			if (pktmbuf_pool[portid][socketid] == NULL)
638ef853f1fSNithin Dabilpuram 				rte_exit(EXIT_FAILURE,
639ef853f1fSNithin Dabilpuram 					 "Cannot init mbuf pool on socket %d\n",
640ef853f1fSNithin Dabilpuram 					 socketid);
641ef853f1fSNithin Dabilpuram 			else
642ef853f1fSNithin Dabilpuram 				printf("Allocated mbuf pool on socket %d\n",
643ef853f1fSNithin Dabilpuram 				       socketid);
644ef853f1fSNithin Dabilpuram 		}
645ef853f1fSNithin Dabilpuram 	}
646ef853f1fSNithin Dabilpuram 
647ef853f1fSNithin Dabilpuram 	return 0;
648ef853f1fSNithin Dabilpuram }
649ef853f1fSNithin Dabilpuram 
650ef853f1fSNithin Dabilpuram /* Check the link status of all ports in up to 9s, and print them finally */
651ef853f1fSNithin Dabilpuram static void
652ef853f1fSNithin Dabilpuram check_all_ports_link_status(uint32_t port_mask)
653ef853f1fSNithin Dabilpuram {
654ef853f1fSNithin Dabilpuram #define CHECK_INTERVAL 100 /* 100ms */
655ef853f1fSNithin Dabilpuram #define MAX_CHECK_TIME 90  /* 9s (90 * 100ms) in total */
656ef853f1fSNithin Dabilpuram 	uint8_t count, all_ports_up, print_flag = 0;
657ef853f1fSNithin Dabilpuram 	struct rte_eth_link link;
658ef853f1fSNithin Dabilpuram 	uint16_t portid;
6591d049dc7SPavan Nikhilesh 	int ret;
660db4e8135SIvan Dyukov 	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
661ef853f1fSNithin Dabilpuram 
662ef853f1fSNithin Dabilpuram 	printf("\nChecking link status");
663ef853f1fSNithin Dabilpuram 	fflush(stdout);
664ef853f1fSNithin Dabilpuram 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
665ef853f1fSNithin Dabilpuram 		if (force_quit)
666ef853f1fSNithin Dabilpuram 			return;
667ef853f1fSNithin Dabilpuram 		all_ports_up = 1;
668ef853f1fSNithin Dabilpuram 		RTE_ETH_FOREACH_DEV(portid)
669ef853f1fSNithin Dabilpuram 		{
670ef853f1fSNithin Dabilpuram 			if (force_quit)
671ef853f1fSNithin Dabilpuram 				return;
672ef853f1fSNithin Dabilpuram 			if ((port_mask & (1 << portid)) == 0)
673ef853f1fSNithin Dabilpuram 				continue;
674ef853f1fSNithin Dabilpuram 			memset(&link, 0, sizeof(link));
6751d049dc7SPavan Nikhilesh 			ret = rte_eth_link_get_nowait(portid, &link);
6761d049dc7SPavan Nikhilesh 			if (ret < 0) {
6771d049dc7SPavan Nikhilesh 				all_ports_up = 0;
6781d049dc7SPavan Nikhilesh 				if (print_flag == 1)
6791d049dc7SPavan Nikhilesh 					printf("Port %u link get failed: %s\n",
6801d049dc7SPavan Nikhilesh 						portid, rte_strerror(-ret));
6811d049dc7SPavan Nikhilesh 				continue;
6821d049dc7SPavan Nikhilesh 			}
683ef853f1fSNithin Dabilpuram 			/* Print link status if flag set */
684ef853f1fSNithin Dabilpuram 			if (print_flag == 1) {
685db4e8135SIvan Dyukov 				rte_eth_link_to_str(link_status_text,
686db4e8135SIvan Dyukov 					sizeof(link_status_text), &link);
687db4e8135SIvan Dyukov 				printf("Port %d %s\n", portid,
688db4e8135SIvan Dyukov 				       link_status_text);
689ef853f1fSNithin Dabilpuram 				continue;
690ef853f1fSNithin Dabilpuram 			}
691ef853f1fSNithin Dabilpuram 			/* Clear all_ports_up flag if any link down */
692295968d1SFerruh Yigit 			if (link.link_status == RTE_ETH_LINK_DOWN) {
693ef853f1fSNithin Dabilpuram 				all_ports_up = 0;
694ef853f1fSNithin Dabilpuram 				break;
695ef853f1fSNithin Dabilpuram 			}
696ef853f1fSNithin Dabilpuram 		}
697ef853f1fSNithin Dabilpuram 		/* After finally printing all link status, get out */
698ef853f1fSNithin Dabilpuram 		if (print_flag == 1)
699ef853f1fSNithin Dabilpuram 			break;
700ef853f1fSNithin Dabilpuram 
701ef853f1fSNithin Dabilpuram 		if (all_ports_up == 0) {
702ef853f1fSNithin Dabilpuram 			printf(".");
703ef853f1fSNithin Dabilpuram 			fflush(stdout);
704ef853f1fSNithin Dabilpuram 			rte_delay_ms(CHECK_INTERVAL);
705ef853f1fSNithin Dabilpuram 		}
706ef853f1fSNithin Dabilpuram 
707ef853f1fSNithin Dabilpuram 		/* Set the print_flag if all ports up or timeout */
708ef853f1fSNithin Dabilpuram 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
709ef853f1fSNithin Dabilpuram 			print_flag = 1;
710ef853f1fSNithin Dabilpuram 			printf("Done\n");
711ef853f1fSNithin Dabilpuram 		}
712ef853f1fSNithin Dabilpuram 	}
713ef853f1fSNithin Dabilpuram }
714ef853f1fSNithin Dabilpuram 
715ef853f1fSNithin Dabilpuram static void
71608bd1a17SNithin Dabilpuram signal_handler(int signum)
71708bd1a17SNithin Dabilpuram {
71808bd1a17SNithin Dabilpuram 	if (signum == SIGINT || signum == SIGTERM) {
71908bd1a17SNithin Dabilpuram 		printf("\n\nSignal %d received, preparing to exit...\n",
72008bd1a17SNithin Dabilpuram 		       signum);
72108bd1a17SNithin Dabilpuram 		force_quit = true;
72208bd1a17SNithin Dabilpuram 	}
72308bd1a17SNithin Dabilpuram }
72408bd1a17SNithin Dabilpuram 
7253087ec1cSNithin Dabilpuram static void
7263087ec1cSNithin Dabilpuram print_stats(void)
7273087ec1cSNithin Dabilpuram {
7283087ec1cSNithin Dabilpuram 	const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'};
7293087ec1cSNithin Dabilpuram 	const char clr[] = {27, '[', '2', 'J', '\0'};
7303087ec1cSNithin Dabilpuram 	struct rte_graph_cluster_stats_param s_param;
7313087ec1cSNithin Dabilpuram 	struct rte_graph_cluster_stats *stats;
7323087ec1cSNithin Dabilpuram 	const char *pattern = "worker_*";
7333087ec1cSNithin Dabilpuram 
7343087ec1cSNithin Dabilpuram 	/* Prepare stats object */
7353087ec1cSNithin Dabilpuram 	memset(&s_param, 0, sizeof(s_param));
7363087ec1cSNithin Dabilpuram 	s_param.f = stdout;
7373087ec1cSNithin Dabilpuram 	s_param.socket_id = SOCKET_ID_ANY;
7383087ec1cSNithin Dabilpuram 	s_param.graph_patterns = &pattern;
7393087ec1cSNithin Dabilpuram 	s_param.nb_graph_patterns = 1;
7403087ec1cSNithin Dabilpuram 
7413087ec1cSNithin Dabilpuram 	stats = rte_graph_cluster_stats_create(&s_param);
7423087ec1cSNithin Dabilpuram 	if (stats == NULL)
7433087ec1cSNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "Unable to create stats object\n");
7443087ec1cSNithin Dabilpuram 
7453087ec1cSNithin Dabilpuram 	while (!force_quit) {
7463087ec1cSNithin Dabilpuram 		/* Clear screen and move to top left */
7473087ec1cSNithin Dabilpuram 		printf("%s%s", clr, topLeft);
7483087ec1cSNithin Dabilpuram 		rte_graph_cluster_stats_get(stats, 0);
7493087ec1cSNithin Dabilpuram 		rte_delay_ms(1E3);
7503087ec1cSNithin Dabilpuram 	}
7513087ec1cSNithin Dabilpuram 
7523087ec1cSNithin Dabilpuram 	rte_graph_cluster_stats_destroy(stats);
7533087ec1cSNithin Dabilpuram }
7543087ec1cSNithin Dabilpuram 
7559a212dc0SConor Fogarty /* Main processing loop. 8< */
7563087ec1cSNithin Dabilpuram static int
7573087ec1cSNithin Dabilpuram graph_main_loop(void *conf)
7583087ec1cSNithin Dabilpuram {
7593087ec1cSNithin Dabilpuram 	struct lcore_conf *qconf;
7603087ec1cSNithin Dabilpuram 	struct rte_graph *graph;
7613087ec1cSNithin Dabilpuram 	uint32_t lcore_id;
7623087ec1cSNithin Dabilpuram 
7633087ec1cSNithin Dabilpuram 	RTE_SET_USED(conf);
7643087ec1cSNithin Dabilpuram 
7653087ec1cSNithin Dabilpuram 	lcore_id = rte_lcore_id();
7663087ec1cSNithin Dabilpuram 	qconf = &lcore_conf[lcore_id];
7673087ec1cSNithin Dabilpuram 	graph = qconf->graph;
7683087ec1cSNithin Dabilpuram 
7693087ec1cSNithin Dabilpuram 	if (!graph) {
7703087ec1cSNithin Dabilpuram 		RTE_LOG(INFO, L3FWD_GRAPH, "Lcore %u has nothing to do\n",
7713087ec1cSNithin Dabilpuram 			lcore_id);
7723087ec1cSNithin Dabilpuram 		return 0;
7733087ec1cSNithin Dabilpuram 	}
7743087ec1cSNithin Dabilpuram 
7753087ec1cSNithin Dabilpuram 	RTE_LOG(INFO, L3FWD_GRAPH,
7763087ec1cSNithin Dabilpuram 		"Entering main loop on lcore %u, graph %s(%p)\n", lcore_id,
7773087ec1cSNithin Dabilpuram 		qconf->name, graph);
7783087ec1cSNithin Dabilpuram 
7793087ec1cSNithin Dabilpuram 	while (likely(!force_quit))
7803087ec1cSNithin Dabilpuram 		rte_graph_walk(graph);
7813087ec1cSNithin Dabilpuram 
7823087ec1cSNithin Dabilpuram 	return 0;
7833087ec1cSNithin Dabilpuram }
7849a212dc0SConor Fogarty /* >8 End of main processing loop. */
7853087ec1cSNithin Dabilpuram 
7861bb4a528SFerruh Yigit static uint32_t
7871bb4a528SFerruh Yigit eth_dev_get_overhead_len(uint32_t max_rx_pktlen, uint16_t max_mtu)
7881bb4a528SFerruh Yigit {
7891bb4a528SFerruh Yigit 	uint32_t overhead_len;
7901bb4a528SFerruh Yigit 
7911bb4a528SFerruh Yigit 	if (max_mtu != UINT16_MAX && max_rx_pktlen > max_mtu)
7921bb4a528SFerruh Yigit 		overhead_len = max_rx_pktlen - max_mtu;
7931bb4a528SFerruh Yigit 	else
7941bb4a528SFerruh Yigit 		overhead_len = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
7951bb4a528SFerruh Yigit 
7961bb4a528SFerruh Yigit 	return overhead_len;
7971bb4a528SFerruh Yigit }
7981bb4a528SFerruh Yigit 
7991bb4a528SFerruh Yigit static int
8001bb4a528SFerruh Yigit config_port_max_pkt_len(struct rte_eth_conf *conf,
8011bb4a528SFerruh Yigit 		struct rte_eth_dev_info *dev_info)
8021bb4a528SFerruh Yigit {
8031bb4a528SFerruh Yigit 	uint32_t overhead_len;
8041bb4a528SFerruh Yigit 
8051bb4a528SFerruh Yigit 	if (max_pkt_len == 0)
8061bb4a528SFerruh Yigit 		return 0;
8071bb4a528SFerruh Yigit 
8081bb4a528SFerruh Yigit 	if (max_pkt_len < RTE_ETHER_MIN_LEN || max_pkt_len > MAX_JUMBO_PKT_LEN)
8091bb4a528SFerruh Yigit 		return -1;
8101bb4a528SFerruh Yigit 
8111bb4a528SFerruh Yigit 	overhead_len = eth_dev_get_overhead_len(dev_info->max_rx_pktlen,
8121bb4a528SFerruh Yigit 			dev_info->max_mtu);
8131bb4a528SFerruh Yigit 	conf->rxmode.mtu = max_pkt_len - overhead_len;
8141bb4a528SFerruh Yigit 
815b563c142SFerruh Yigit 	if (conf->rxmode.mtu > RTE_ETHER_MTU)
816295968d1SFerruh Yigit 		conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
8171bb4a528SFerruh Yigit 
8181bb4a528SFerruh Yigit 	return 0;
8191bb4a528SFerruh Yigit }
8201bb4a528SFerruh Yigit 
82108bd1a17SNithin Dabilpuram int
82208bd1a17SNithin Dabilpuram main(int argc, char **argv)
82308bd1a17SNithin Dabilpuram {
8243087ec1cSNithin Dabilpuram 	/* Rewrite data of src and dst ether addr */
8253087ec1cSNithin Dabilpuram 	uint8_t rewrite_data[2 * sizeof(struct rte_ether_addr)];
8269a212dc0SConor Fogarty 	/* Graph initialization. 8< */
8273087ec1cSNithin Dabilpuram 	static const char * const default_patterns[] = {
8283087ec1cSNithin Dabilpuram 		"ip4*",
8293087ec1cSNithin Dabilpuram 		"ethdev_tx-*",
8303087ec1cSNithin Dabilpuram 		"pkt_drop",
8313087ec1cSNithin Dabilpuram 	};
832ef853f1fSNithin Dabilpuram 	uint8_t nb_rx_queue, queue, socketid;
8333087ec1cSNithin Dabilpuram 	struct rte_graph_param graph_conf;
834ef853f1fSNithin Dabilpuram 	struct rte_eth_dev_info dev_info;
8353087ec1cSNithin Dabilpuram 	uint32_t nb_ports, nb_conf = 0;
836ef853f1fSNithin Dabilpuram 	uint32_t n_tx_queue, nb_lcores;
837ef853f1fSNithin Dabilpuram 	struct rte_eth_txconf *txconf;
8383087ec1cSNithin Dabilpuram 	uint16_t queueid, portid, i;
8393087ec1cSNithin Dabilpuram 	const char **node_patterns;
840ef853f1fSNithin Dabilpuram 	struct lcore_conf *qconf;
8413087ec1cSNithin Dabilpuram 	uint16_t nb_graphs = 0;
8423087ec1cSNithin Dabilpuram 	uint16_t nb_patterns;
8433087ec1cSNithin Dabilpuram 	uint8_t rewrite_len;
844ef853f1fSNithin Dabilpuram 	uint32_t lcore_id;
84508bd1a17SNithin Dabilpuram 	int ret;
84608bd1a17SNithin Dabilpuram 
84708bd1a17SNithin Dabilpuram 	/* Init EAL */
84808bd1a17SNithin Dabilpuram 	ret = rte_eal_init(argc, argv);
84908bd1a17SNithin Dabilpuram 	if (ret < 0)
85008bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
85108bd1a17SNithin Dabilpuram 	argc -= ret;
85208bd1a17SNithin Dabilpuram 	argv += ret;
85308bd1a17SNithin Dabilpuram 
85408bd1a17SNithin Dabilpuram 	force_quit = false;
85508bd1a17SNithin Dabilpuram 	signal(SIGINT, signal_handler);
85608bd1a17SNithin Dabilpuram 	signal(SIGTERM, signal_handler);
85708bd1a17SNithin Dabilpuram 
85808bd1a17SNithin Dabilpuram 	/* Pre-init dst MACs for all ports to 02:00:00:00:00:xx */
85908bd1a17SNithin Dabilpuram 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
86008bd1a17SNithin Dabilpuram 		dest_eth_addr[portid] =
86108bd1a17SNithin Dabilpuram 			RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40);
86208bd1a17SNithin Dabilpuram 		*(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
86308bd1a17SNithin Dabilpuram 	}
86408bd1a17SNithin Dabilpuram 
86508bd1a17SNithin Dabilpuram 	/* Parse application arguments (after the EAL ones) */
86608bd1a17SNithin Dabilpuram 	ret = parse_args(argc, argv);
86708bd1a17SNithin Dabilpuram 	if (ret < 0)
86808bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "Invalid L3FWD_GRAPH parameters\n");
86908bd1a17SNithin Dabilpuram 
87008bd1a17SNithin Dabilpuram 	if (check_lcore_params() < 0)
87108bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "check_lcore_params() failed\n");
87208bd1a17SNithin Dabilpuram 
87308bd1a17SNithin Dabilpuram 	ret = init_lcore_rx_queues();
87408bd1a17SNithin Dabilpuram 	if (ret < 0)
87508bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "init_lcore_rx_queues() failed\n");
87608bd1a17SNithin Dabilpuram 
87708bd1a17SNithin Dabilpuram 	if (check_port_config() < 0)
87808bd1a17SNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "check_port_config() failed\n");
87908bd1a17SNithin Dabilpuram 
880ef853f1fSNithin Dabilpuram 	nb_ports = rte_eth_dev_count_avail();
881ef853f1fSNithin Dabilpuram 	nb_lcores = rte_lcore_count();
882ef853f1fSNithin Dabilpuram 
8839a212dc0SConor Fogarty 	/* Initialize all ports. 8< */
884ef853f1fSNithin Dabilpuram 	RTE_ETH_FOREACH_DEV(portid)
885ef853f1fSNithin Dabilpuram 	{
886ef853f1fSNithin Dabilpuram 		struct rte_eth_conf local_port_conf = port_conf;
887ef853f1fSNithin Dabilpuram 
888ef853f1fSNithin Dabilpuram 		/* Skip ports that are not enabled */
889ef853f1fSNithin Dabilpuram 		if ((enabled_port_mask & (1 << portid)) == 0) {
890ef853f1fSNithin Dabilpuram 			printf("\nSkipping disabled port %d\n", portid);
891ef853f1fSNithin Dabilpuram 			continue;
892ef853f1fSNithin Dabilpuram 		}
893ef853f1fSNithin Dabilpuram 
894ef853f1fSNithin Dabilpuram 		/* Init port */
895ef853f1fSNithin Dabilpuram 		printf("Initializing port %d ... ", portid);
896ef853f1fSNithin Dabilpuram 		fflush(stdout);
897ef853f1fSNithin Dabilpuram 
898ef853f1fSNithin Dabilpuram 		nb_rx_queue = get_port_n_rx_queues(portid);
899ef853f1fSNithin Dabilpuram 		n_tx_queue = nb_lcores;
900ef853f1fSNithin Dabilpuram 		if (n_tx_queue > MAX_TX_QUEUE_PER_PORT)
901ef853f1fSNithin Dabilpuram 			n_tx_queue = MAX_TX_QUEUE_PER_PORT;
902ef853f1fSNithin Dabilpuram 		printf("Creating queues: nb_rxq=%d nb_txq=%u... ",
903ef853f1fSNithin Dabilpuram 		       nb_rx_queue, n_tx_queue);
904ef853f1fSNithin Dabilpuram 
905ef853f1fSNithin Dabilpuram 		rte_eth_dev_info_get(portid, &dev_info);
9061bb4a528SFerruh Yigit 
9071bb4a528SFerruh Yigit 		ret = config_port_max_pkt_len(&local_port_conf, &dev_info);
9081bb4a528SFerruh Yigit 		if (ret != 0)
9091bb4a528SFerruh Yigit 			rte_exit(EXIT_FAILURE,
9101bb4a528SFerruh Yigit 				"Invalid max packet length: %u (port %u)\n",
9111bb4a528SFerruh Yigit 				max_pkt_len, portid);
9121bb4a528SFerruh Yigit 
913295968d1SFerruh Yigit 		if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
914ef853f1fSNithin Dabilpuram 			local_port_conf.txmode.offloads |=
915295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
916ef853f1fSNithin Dabilpuram 
917ef853f1fSNithin Dabilpuram 		local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
918ef853f1fSNithin Dabilpuram 			dev_info.flow_type_rss_offloads;
919ef853f1fSNithin Dabilpuram 		if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
920ef853f1fSNithin Dabilpuram 		    port_conf.rx_adv_conf.rss_conf.rss_hf) {
921ef853f1fSNithin Dabilpuram 			printf("Port %u modified RSS hash function based on "
922ef853f1fSNithin Dabilpuram 			       "hardware support,"
923ef853f1fSNithin Dabilpuram 			       "requested:%#" PRIx64 " configured:%#" PRIx64
924ef853f1fSNithin Dabilpuram 			       "\n",
925ef853f1fSNithin Dabilpuram 			       portid, port_conf.rx_adv_conf.rss_conf.rss_hf,
926ef853f1fSNithin Dabilpuram 			       local_port_conf.rx_adv_conf.rss_conf.rss_hf);
927ef853f1fSNithin Dabilpuram 		}
928ef853f1fSNithin Dabilpuram 
929ef853f1fSNithin Dabilpuram 		ret = rte_eth_dev_configure(portid, nb_rx_queue,
930ef853f1fSNithin Dabilpuram 					    n_tx_queue, &local_port_conf);
931ef853f1fSNithin Dabilpuram 		if (ret < 0)
932ef853f1fSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
933ef853f1fSNithin Dabilpuram 				 "Cannot configure device: err=%d, port=%d\n",
934ef853f1fSNithin Dabilpuram 				 ret, portid);
935ef853f1fSNithin Dabilpuram 
936ef853f1fSNithin Dabilpuram 		ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
937ef853f1fSNithin Dabilpuram 						       &nb_txd);
938ef853f1fSNithin Dabilpuram 		if (ret < 0)
939ef853f1fSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
940ef853f1fSNithin Dabilpuram 				 "Cannot adjust number of descriptors: err=%d, "
941ef853f1fSNithin Dabilpuram 				 "port=%d\n",
942ef853f1fSNithin Dabilpuram 				 ret, portid);
943ef853f1fSNithin Dabilpuram 
944ef853f1fSNithin Dabilpuram 		rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
945ef853f1fSNithin Dabilpuram 		print_ethaddr(" Address:", &ports_eth_addr[portid]);
946ef853f1fSNithin Dabilpuram 		printf(", ");
947ef853f1fSNithin Dabilpuram 		print_ethaddr(
948ef853f1fSNithin Dabilpuram 			"Destination:",
949ef853f1fSNithin Dabilpuram 			(const struct rte_ether_addr *)&dest_eth_addr[portid]);
950ef853f1fSNithin Dabilpuram 		printf(", ");
951ef853f1fSNithin Dabilpuram 
952ef853f1fSNithin Dabilpuram 		/*
953ef853f1fSNithin Dabilpuram 		 * prepare src MACs for each port.
954ef853f1fSNithin Dabilpuram 		 */
955ef853f1fSNithin Dabilpuram 		rte_ether_addr_copy(
956ef853f1fSNithin Dabilpuram 			&ports_eth_addr[portid],
957ef853f1fSNithin Dabilpuram 			(struct rte_ether_addr *)(val_eth + portid) + 1);
958ef853f1fSNithin Dabilpuram 
959ef853f1fSNithin Dabilpuram 		/* Init memory */
960ef853f1fSNithin Dabilpuram 		if (!per_port_pool) {
961ef853f1fSNithin Dabilpuram 			/* portid = 0; this is *not* signifying the first port,
962ef853f1fSNithin Dabilpuram 			 * rather, it signifies that portid is ignored.
963ef853f1fSNithin Dabilpuram 			 */
964ef853f1fSNithin Dabilpuram 			ret = init_mem(0, NB_MBUF(nb_ports));
965ef853f1fSNithin Dabilpuram 		} else {
966ef853f1fSNithin Dabilpuram 			ret = init_mem(portid, NB_MBUF(1));
967ef853f1fSNithin Dabilpuram 		}
968ef853f1fSNithin Dabilpuram 		if (ret < 0)
969ef853f1fSNithin Dabilpuram 			rte_exit(EXIT_FAILURE, "init_mem() failed\n");
970ef853f1fSNithin Dabilpuram 
971ef853f1fSNithin Dabilpuram 		/* Init one TX queue per couple (lcore,port) */
972ef853f1fSNithin Dabilpuram 		queueid = 0;
973ef853f1fSNithin Dabilpuram 		for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
974ef853f1fSNithin Dabilpuram 			if (rte_lcore_is_enabled(lcore_id) == 0)
975ef853f1fSNithin Dabilpuram 				continue;
976ef853f1fSNithin Dabilpuram 
977ef853f1fSNithin Dabilpuram 			qconf = &lcore_conf[lcore_id];
978ef853f1fSNithin Dabilpuram 
979ef853f1fSNithin Dabilpuram 			if (numa_on)
980ef853f1fSNithin Dabilpuram 				socketid = (uint8_t)rte_lcore_to_socket_id(
981ef853f1fSNithin Dabilpuram 					lcore_id);
982ef853f1fSNithin Dabilpuram 			else
983ef853f1fSNithin Dabilpuram 				socketid = 0;
984ef853f1fSNithin Dabilpuram 
985ef853f1fSNithin Dabilpuram 			printf("txq=%u,%d,%d ", lcore_id, queueid, socketid);
986ef853f1fSNithin Dabilpuram 			fflush(stdout);
987ef853f1fSNithin Dabilpuram 
988ef853f1fSNithin Dabilpuram 			txconf = &dev_info.default_txconf;
989ef853f1fSNithin Dabilpuram 			txconf->offloads = local_port_conf.txmode.offloads;
990ef853f1fSNithin Dabilpuram 			ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
991ef853f1fSNithin Dabilpuram 						     socketid, txconf);
992ef853f1fSNithin Dabilpuram 			if (ret < 0)
993ef853f1fSNithin Dabilpuram 				rte_exit(EXIT_FAILURE,
994ef853f1fSNithin Dabilpuram 					 "rte_eth_tx_queue_setup: err=%d, "
995ef853f1fSNithin Dabilpuram 					 "port=%d\n",
996ef853f1fSNithin Dabilpuram 					 ret, portid);
997ef853f1fSNithin Dabilpuram 			queueid++;
998ef853f1fSNithin Dabilpuram 		}
999ef853f1fSNithin Dabilpuram 
10003087ec1cSNithin Dabilpuram 		/* Setup ethdev node config */
10013087ec1cSNithin Dabilpuram 		ethdev_conf[nb_conf].port_id = portid;
10023087ec1cSNithin Dabilpuram 		ethdev_conf[nb_conf].num_rx_queues = nb_rx_queue;
10033087ec1cSNithin Dabilpuram 		ethdev_conf[nb_conf].num_tx_queues = n_tx_queue;
10043087ec1cSNithin Dabilpuram 		if (!per_port_pool)
10053087ec1cSNithin Dabilpuram 			ethdev_conf[nb_conf].mp = pktmbuf_pool[0];
10063087ec1cSNithin Dabilpuram 
10073087ec1cSNithin Dabilpuram 		else
10083087ec1cSNithin Dabilpuram 			ethdev_conf[nb_conf].mp = pktmbuf_pool[portid];
10093087ec1cSNithin Dabilpuram 		ethdev_conf[nb_conf].mp_count = NB_SOCKETS;
10103087ec1cSNithin Dabilpuram 
10113087ec1cSNithin Dabilpuram 		nb_conf++;
1012ef853f1fSNithin Dabilpuram 		printf("\n");
1013ef853f1fSNithin Dabilpuram 	}
1014ef853f1fSNithin Dabilpuram 
1015ef853f1fSNithin Dabilpuram 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1016ef853f1fSNithin Dabilpuram 		if (rte_lcore_is_enabled(lcore_id) == 0)
1017ef853f1fSNithin Dabilpuram 			continue;
1018ef853f1fSNithin Dabilpuram 		qconf = &lcore_conf[lcore_id];
1019ef853f1fSNithin Dabilpuram 		printf("\nInitializing rx queues on lcore %u ... ", lcore_id);
1020ef853f1fSNithin Dabilpuram 		fflush(stdout);
1021ef853f1fSNithin Dabilpuram 		/* Init RX queues */
1022ef853f1fSNithin Dabilpuram 		for (queue = 0; queue < qconf->n_rx_queue; ++queue) {
1023ef853f1fSNithin Dabilpuram 			struct rte_eth_rxconf rxq_conf;
1024ef853f1fSNithin Dabilpuram 
1025ef853f1fSNithin Dabilpuram 			portid = qconf->rx_queue_list[queue].port_id;
1026ef853f1fSNithin Dabilpuram 			queueid = qconf->rx_queue_list[queue].queue_id;
1027ef853f1fSNithin Dabilpuram 
1028ef853f1fSNithin Dabilpuram 			if (numa_on)
1029ef853f1fSNithin Dabilpuram 				socketid = (uint8_t)rte_lcore_to_socket_id(
1030ef853f1fSNithin Dabilpuram 					lcore_id);
1031ef853f1fSNithin Dabilpuram 			else
1032ef853f1fSNithin Dabilpuram 				socketid = 0;
1033ef853f1fSNithin Dabilpuram 
1034ef853f1fSNithin Dabilpuram 			printf("rxq=%d,%d,%d ", portid, queueid, socketid);
1035ef853f1fSNithin Dabilpuram 			fflush(stdout);
1036ef853f1fSNithin Dabilpuram 
1037ef853f1fSNithin Dabilpuram 			rte_eth_dev_info_get(portid, &dev_info);
1038ef853f1fSNithin Dabilpuram 			rxq_conf = dev_info.default_rxconf;
1039ef853f1fSNithin Dabilpuram 			rxq_conf.offloads = port_conf.rxmode.offloads;
1040ef853f1fSNithin Dabilpuram 			if (!per_port_pool)
1041ef853f1fSNithin Dabilpuram 				ret = rte_eth_rx_queue_setup(
1042ef853f1fSNithin Dabilpuram 					portid, queueid, nb_rxd, socketid,
1043ef853f1fSNithin Dabilpuram 					&rxq_conf, pktmbuf_pool[0][socketid]);
1044ef853f1fSNithin Dabilpuram 			else
1045ef853f1fSNithin Dabilpuram 				ret = rte_eth_rx_queue_setup(
1046ef853f1fSNithin Dabilpuram 					portid, queueid, nb_rxd, socketid,
1047ef853f1fSNithin Dabilpuram 					&rxq_conf,
1048ef853f1fSNithin Dabilpuram 					pktmbuf_pool[portid][socketid]);
1049ef853f1fSNithin Dabilpuram 			if (ret < 0)
1050ef853f1fSNithin Dabilpuram 				rte_exit(EXIT_FAILURE,
1051ef853f1fSNithin Dabilpuram 					 "rte_eth_rx_queue_setup: err=%d, "
1052ef853f1fSNithin Dabilpuram 					 "port=%d\n",
1053ef853f1fSNithin Dabilpuram 					 ret, portid);
1054ef853f1fSNithin Dabilpuram 
10553087ec1cSNithin Dabilpuram 			/* Add this queue node to its graph */
10563087ec1cSNithin Dabilpuram 			snprintf(qconf->rx_queue_list[queue].node_name,
10573087ec1cSNithin Dabilpuram 				 RTE_NODE_NAMESIZE, "ethdev_rx-%u-%u", portid,
10583087ec1cSNithin Dabilpuram 				 queueid);
1059ef853f1fSNithin Dabilpuram 		}
10603087ec1cSNithin Dabilpuram 
10613087ec1cSNithin Dabilpuram 		/* Alloc a graph to this lcore only if source exists  */
10623087ec1cSNithin Dabilpuram 		if (qconf->n_rx_queue)
10633087ec1cSNithin Dabilpuram 			nb_graphs++;
1064ef853f1fSNithin Dabilpuram 	}
1065ef853f1fSNithin Dabilpuram 
1066ef853f1fSNithin Dabilpuram 	printf("\n");
1067ef853f1fSNithin Dabilpuram 
10683087ec1cSNithin Dabilpuram 	/* Ethdev node config, skip rx queue mapping */
10693087ec1cSNithin Dabilpuram 	ret = rte_node_eth_config(ethdev_conf, nb_conf, nb_graphs);
10709a212dc0SConor Fogarty 	/* >8 End of graph creation. */
10713087ec1cSNithin Dabilpuram 	if (ret)
10723087ec1cSNithin Dabilpuram 		rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", ret);
10733087ec1cSNithin Dabilpuram 
1074ef853f1fSNithin Dabilpuram 	/* Start ports */
1075ef853f1fSNithin Dabilpuram 	RTE_ETH_FOREACH_DEV(portid)
1076ef853f1fSNithin Dabilpuram 	{
1077ef853f1fSNithin Dabilpuram 		if ((enabled_port_mask & (1 << portid)) == 0)
1078ef853f1fSNithin Dabilpuram 			continue;
1079ef853f1fSNithin Dabilpuram 
1080ef853f1fSNithin Dabilpuram 		/* Start device */
1081ef853f1fSNithin Dabilpuram 		ret = rte_eth_dev_start(portid);
1082ef853f1fSNithin Dabilpuram 		if (ret < 0)
1083ef853f1fSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
1084ef853f1fSNithin Dabilpuram 				 "rte_eth_dev_start: err=%d, port=%d\n", ret,
1085ef853f1fSNithin Dabilpuram 				 portid);
1086ef853f1fSNithin Dabilpuram 
1087ef853f1fSNithin Dabilpuram 		/*
1088ef853f1fSNithin Dabilpuram 		 * If enabled, put device in promiscuous mode.
1089ef853f1fSNithin Dabilpuram 		 * This allows IO forwarding mode to forward packets
1090ef853f1fSNithin Dabilpuram 		 * to itself through 2 cross-connected  ports of the
1091ef853f1fSNithin Dabilpuram 		 * target machine.
1092ef853f1fSNithin Dabilpuram 		 */
1093ef853f1fSNithin Dabilpuram 		if (promiscuous_on)
1094ef853f1fSNithin Dabilpuram 			rte_eth_promiscuous_enable(portid);
1095ef853f1fSNithin Dabilpuram 	}
1096ef853f1fSNithin Dabilpuram 
1097ef853f1fSNithin Dabilpuram 	printf("\n");
1098ef853f1fSNithin Dabilpuram 
1099ef853f1fSNithin Dabilpuram 	check_all_ports_link_status(enabled_port_mask);
1100ef853f1fSNithin Dabilpuram 
11013087ec1cSNithin Dabilpuram 	/* Graph Initialization */
11023087ec1cSNithin Dabilpuram 	nb_patterns = RTE_DIM(default_patterns);
11033087ec1cSNithin Dabilpuram 	node_patterns = malloc((MAX_RX_QUEUE_PER_LCORE + nb_patterns) *
11043087ec1cSNithin Dabilpuram 			       sizeof(*node_patterns));
11053087ec1cSNithin Dabilpuram 	if (!node_patterns)
11063087ec1cSNithin Dabilpuram 		return -ENOMEM;
11073087ec1cSNithin Dabilpuram 	memcpy(node_patterns, default_patterns,
11083087ec1cSNithin Dabilpuram 	       nb_patterns * sizeof(*node_patterns));
11093087ec1cSNithin Dabilpuram 
11103087ec1cSNithin Dabilpuram 	memset(&graph_conf, 0, sizeof(graph_conf));
11113087ec1cSNithin Dabilpuram 	graph_conf.node_patterns = node_patterns;
11123087ec1cSNithin Dabilpuram 
11139b72ea1fSAmit Prakash Shukla 	/* Pcap config */
11149b72ea1fSAmit Prakash Shukla 	graph_conf.pcap_enable = pcap_trace_enable;
11159b72ea1fSAmit Prakash Shukla 	graph_conf.num_pkt_to_capture = packet_to_capture;
11169b72ea1fSAmit Prakash Shukla 	graph_conf.pcap_filename = pcap_filename;
11179b72ea1fSAmit Prakash Shukla 
11183087ec1cSNithin Dabilpuram 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
11193087ec1cSNithin Dabilpuram 		rte_graph_t graph_id;
11203087ec1cSNithin Dabilpuram 		rte_edge_t i;
11213087ec1cSNithin Dabilpuram 
11223087ec1cSNithin Dabilpuram 		if (rte_lcore_is_enabled(lcore_id) == 0)
11233087ec1cSNithin Dabilpuram 			continue;
11243087ec1cSNithin Dabilpuram 
11253087ec1cSNithin Dabilpuram 		qconf = &lcore_conf[lcore_id];
11263087ec1cSNithin Dabilpuram 
11273087ec1cSNithin Dabilpuram 		/* Skip graph creation if no source exists */
11283087ec1cSNithin Dabilpuram 		if (!qconf->n_rx_queue)
11293087ec1cSNithin Dabilpuram 			continue;
11303087ec1cSNithin Dabilpuram 
11313087ec1cSNithin Dabilpuram 		/* Add rx node patterns of this lcore */
11323087ec1cSNithin Dabilpuram 		for (i = 0; i < qconf->n_rx_queue; i++) {
11333087ec1cSNithin Dabilpuram 			graph_conf.node_patterns[nb_patterns + i] =
11343087ec1cSNithin Dabilpuram 				qconf->rx_queue_list[i].node_name;
11353087ec1cSNithin Dabilpuram 		}
11363087ec1cSNithin Dabilpuram 
11373087ec1cSNithin Dabilpuram 		graph_conf.nb_node_patterns = nb_patterns + i;
11383087ec1cSNithin Dabilpuram 		graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id);
11393087ec1cSNithin Dabilpuram 
11403087ec1cSNithin Dabilpuram 		snprintf(qconf->name, sizeof(qconf->name), "worker_%u",
11413087ec1cSNithin Dabilpuram 			 lcore_id);
11423087ec1cSNithin Dabilpuram 
11433087ec1cSNithin Dabilpuram 		graph_id = rte_graph_create(qconf->name, &graph_conf);
11443087ec1cSNithin Dabilpuram 		if (graph_id == RTE_GRAPH_ID_INVALID)
11453087ec1cSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
11463087ec1cSNithin Dabilpuram 				 "rte_graph_create(): graph_id invalid"
11473087ec1cSNithin Dabilpuram 				 " for lcore %u\n", lcore_id);
11483087ec1cSNithin Dabilpuram 
11493087ec1cSNithin Dabilpuram 		qconf->graph_id = graph_id;
11503087ec1cSNithin Dabilpuram 		qconf->graph = rte_graph_lookup(qconf->name);
11519a212dc0SConor Fogarty 		/* >8 End of graph initialization. */
11523087ec1cSNithin Dabilpuram 		if (!qconf->graph)
11533087ec1cSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
11543087ec1cSNithin Dabilpuram 				 "rte_graph_lookup(): graph %s not found\n",
11553087ec1cSNithin Dabilpuram 				 qconf->name);
11563087ec1cSNithin Dabilpuram 	}
11573087ec1cSNithin Dabilpuram 
11583087ec1cSNithin Dabilpuram 	memset(&rewrite_data, 0, sizeof(rewrite_data));
11593087ec1cSNithin Dabilpuram 	rewrite_len = sizeof(rewrite_data);
11603087ec1cSNithin Dabilpuram 
11617fc2cdf2SSunil Kumar Kori 	/* Add routes and rewrite data to graph infra. 8< */
11623087ec1cSNithin Dabilpuram 	for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {
11633087ec1cSNithin Dabilpuram 		char route_str[INET6_ADDRSTRLEN * 4];
11643087ec1cSNithin Dabilpuram 		char abuf[INET6_ADDRSTRLEN];
11653087ec1cSNithin Dabilpuram 		struct in_addr in;
11663087ec1cSNithin Dabilpuram 		uint32_t dst_port;
11673087ec1cSNithin Dabilpuram 
11683087ec1cSNithin Dabilpuram 		/* Skip unused ports */
11693087ec1cSNithin Dabilpuram 		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
11703087ec1cSNithin Dabilpuram 		     enabled_port_mask) == 0)
11713087ec1cSNithin Dabilpuram 			continue;
11723087ec1cSNithin Dabilpuram 
11733087ec1cSNithin Dabilpuram 		dst_port = ipv4_l3fwd_lpm_route_array[i].if_out;
11743087ec1cSNithin Dabilpuram 
11753087ec1cSNithin Dabilpuram 		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
11763087ec1cSNithin Dabilpuram 		snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
11773087ec1cSNithin Dabilpuram 			 inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
11783087ec1cSNithin Dabilpuram 			 ipv4_l3fwd_lpm_route_array[i].depth,
11793087ec1cSNithin Dabilpuram 			 ipv4_l3fwd_lpm_route_array[i].if_out);
11803087ec1cSNithin Dabilpuram 
11813087ec1cSNithin Dabilpuram 		/* Use route index 'i' as next hop id */
11823087ec1cSNithin Dabilpuram 		ret = rte_node_ip4_route_add(
11833087ec1cSNithin Dabilpuram 			ipv4_l3fwd_lpm_route_array[i].ip,
11843087ec1cSNithin Dabilpuram 			ipv4_l3fwd_lpm_route_array[i].depth, i,
11853087ec1cSNithin Dabilpuram 			RTE_NODE_IP4_LOOKUP_NEXT_REWRITE);
11863087ec1cSNithin Dabilpuram 
11873087ec1cSNithin Dabilpuram 		if (ret < 0)
11883087ec1cSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
11893087ec1cSNithin Dabilpuram 				 "Unable to add ip4 route %s to graph\n",
11903087ec1cSNithin Dabilpuram 				 route_str);
11913087ec1cSNithin Dabilpuram 
11923087ec1cSNithin Dabilpuram 		memcpy(rewrite_data, val_eth + dst_port, rewrite_len);
11933087ec1cSNithin Dabilpuram 
11943087ec1cSNithin Dabilpuram 		/* Add next hop rewrite data for id 'i' */
11953087ec1cSNithin Dabilpuram 		ret = rte_node_ip4_rewrite_add(i, rewrite_data,
11963087ec1cSNithin Dabilpuram 					       rewrite_len, dst_port);
11973087ec1cSNithin Dabilpuram 		if (ret < 0)
11983087ec1cSNithin Dabilpuram 			rte_exit(EXIT_FAILURE,
11993087ec1cSNithin Dabilpuram 				 "Unable to add next hop %u for "
12003087ec1cSNithin Dabilpuram 				 "route %s\n", i, route_str);
12013087ec1cSNithin Dabilpuram 
12023087ec1cSNithin Dabilpuram 		RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
12033087ec1cSNithin Dabilpuram 			route_str, i);
12043087ec1cSNithin Dabilpuram 	}
12057fc2cdf2SSunil Kumar Kori 
12067fc2cdf2SSunil Kumar Kori 	for (i = 0; i < IPV6_L3FWD_LPM_NUM_ROUTES; i++) {
12077fc2cdf2SSunil Kumar Kori 		char route_str[INET6_ADDRSTRLEN * 4];
12087fc2cdf2SSunil Kumar Kori 		char abuf[INET6_ADDRSTRLEN];
12097fc2cdf2SSunil Kumar Kori 		struct in6_addr in6;
12107fc2cdf2SSunil Kumar Kori 		uint32_t dst_port;
12117fc2cdf2SSunil Kumar Kori 
12127fc2cdf2SSunil Kumar Kori 		/* Skip unused ports */
12137fc2cdf2SSunil Kumar Kori 		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
12147fc2cdf2SSunil Kumar Kori 		     enabled_port_mask) == 0)
12157fc2cdf2SSunil Kumar Kori 			continue;
12167fc2cdf2SSunil Kumar Kori 
12177fc2cdf2SSunil Kumar Kori 		dst_port = ipv6_l3fwd_lpm_route_array[i].if_out;
12187fc2cdf2SSunil Kumar Kori 
12197fc2cdf2SSunil Kumar Kori 		memcpy(in6.s6_addr, ipv6_l3fwd_lpm_route_array[i].ip, RTE_LPM6_IPV6_ADDR_SIZE);
12207fc2cdf2SSunil Kumar Kori 		snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
12217fc2cdf2SSunil Kumar Kori 			 inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)),
12227fc2cdf2SSunil Kumar Kori 			 ipv6_l3fwd_lpm_route_array[i].depth,
12237fc2cdf2SSunil Kumar Kori 			 ipv6_l3fwd_lpm_route_array[i].if_out);
12247fc2cdf2SSunil Kumar Kori 
12257fc2cdf2SSunil Kumar Kori 		/* Use route index 'i' as next hop id */
12267fc2cdf2SSunil Kumar Kori 		ret = rte_node_ip6_route_add(ipv6_l3fwd_lpm_route_array[i].ip,
12277fc2cdf2SSunil Kumar Kori 			ipv6_l3fwd_lpm_route_array[i].depth, i,
12287fc2cdf2SSunil Kumar Kori 			RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
12297fc2cdf2SSunil Kumar Kori 
12307fc2cdf2SSunil Kumar Kori 		if (ret < 0)
12317fc2cdf2SSunil Kumar Kori 			rte_exit(EXIT_FAILURE,
12327fc2cdf2SSunil Kumar Kori 				 "Unable to add ip6 route %s to graph\n",
12337fc2cdf2SSunil Kumar Kori 				 route_str);
12347fc2cdf2SSunil Kumar Kori 
12357fc2cdf2SSunil Kumar Kori 		memcpy(rewrite_data, val_eth + dst_port, rewrite_len);
12367fc2cdf2SSunil Kumar Kori 
12377fc2cdf2SSunil Kumar Kori 		/* Add next hop rewrite data for id 'i' */
12387fc2cdf2SSunil Kumar Kori 		ret = rte_node_ip6_rewrite_add(i, rewrite_data,
12397fc2cdf2SSunil Kumar Kori 					       rewrite_len, dst_port);
12407fc2cdf2SSunil Kumar Kori 		if (ret < 0)
12417fc2cdf2SSunil Kumar Kori 			rte_exit(EXIT_FAILURE,
12427fc2cdf2SSunil Kumar Kori 				 "Unable to add next hop %u for "
12437fc2cdf2SSunil Kumar Kori 				 "route %s\n", i, route_str);
12447fc2cdf2SSunil Kumar Kori 
12457fc2cdf2SSunil Kumar Kori 		RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
12467fc2cdf2SSunil Kumar Kori 			route_str, i);
12477fc2cdf2SSunil Kumar Kori 	}
12487fc2cdf2SSunil Kumar Kori 	/* >8 End of adding routes and rewrite data to graph infa. */
12493087ec1cSNithin Dabilpuram 
1250cb056611SStephen Hemminger 	/* Launch per-lcore init on every worker lcore */
1251cb056611SStephen Hemminger 	rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);
12523087ec1cSNithin Dabilpuram 
1253cb056611SStephen Hemminger 	/* Accumulate and print stats on main until exit */
12543087ec1cSNithin Dabilpuram 	if (rte_graph_has_stats_feature())
12553087ec1cSNithin Dabilpuram 		print_stats();
12563087ec1cSNithin Dabilpuram 
1257cb056611SStephen Hemminger 	/* Wait for worker cores to exit */
12583087ec1cSNithin Dabilpuram 	ret = 0;
1259cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
12603087ec1cSNithin Dabilpuram 		ret = rte_eal_wait_lcore(lcore_id);
12613087ec1cSNithin Dabilpuram 		/* Destroy graph */
12623087ec1cSNithin Dabilpuram 		if (ret < 0 || rte_graph_destroy(
12633087ec1cSNithin Dabilpuram 			rte_graph_from_name(lcore_conf[lcore_id].name))) {
12643087ec1cSNithin Dabilpuram 			ret = -1;
12653087ec1cSNithin Dabilpuram 			break;
12663087ec1cSNithin Dabilpuram 		}
12673087ec1cSNithin Dabilpuram 	}
12683087ec1cSNithin Dabilpuram 	free(node_patterns);
12693087ec1cSNithin Dabilpuram 
1270ef853f1fSNithin Dabilpuram 	/* Stop ports */
1271ef853f1fSNithin Dabilpuram 	RTE_ETH_FOREACH_DEV(portid) {
1272ef853f1fSNithin Dabilpuram 		if ((enabled_port_mask & (1 << portid)) == 0)
1273ef853f1fSNithin Dabilpuram 			continue;
1274ef853f1fSNithin Dabilpuram 		printf("Closing port %d...", portid);
1275b55efbabSIvan Ilchenko 		ret = rte_eth_dev_stop(portid);
1276b55efbabSIvan Ilchenko 		if (ret != 0)
1277b55efbabSIvan Ilchenko 			printf("Failed to stop port %u: %s\n",
1278b55efbabSIvan Ilchenko 			       portid, rte_strerror(-ret));
1279ef853f1fSNithin Dabilpuram 		rte_eth_dev_close(portid);
1280ef853f1fSNithin Dabilpuram 		printf(" Done\n");
1281ef853f1fSNithin Dabilpuram 	}
128210aa3757SChengchang Tang 
128310aa3757SChengchang Tang 	/* clean up the EAL */
128410aa3757SChengchang Tang 	rte_eal_cleanup();
128508bd1a17SNithin Dabilpuram 	printf("Bye...\n");
128608bd1a17SNithin Dabilpuram 
128708bd1a17SNithin Dabilpuram 	return ret;
128808bd1a17SNithin Dabilpuram }
1289