xref: /dpdk/examples/bond/main.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2010-2015 Intel Corporation
3cc7e8ae8SMichal Jastrzebski  */
4cc7e8ae8SMichal Jastrzebski 
5cc7e8ae8SMichal Jastrzebski #include <stdint.h>
6cc7e8ae8SMichal Jastrzebski #include <sys/queue.h>
756faae82SDaniel Mrzyglod #include <sys/socket.h>
8cc7e8ae8SMichal Jastrzebski #include <stdlib.h>
9cc7e8ae8SMichal Jastrzebski #include <string.h>
10cc7e8ae8SMichal Jastrzebski #include <stdio.h>
11cc7e8ae8SMichal Jastrzebski #include <assert.h>
12cc7e8ae8SMichal Jastrzebski #include <errno.h>
13cc7e8ae8SMichal Jastrzebski #include <signal.h>
14cc7e8ae8SMichal Jastrzebski #include <stdarg.h>
15cc7e8ae8SMichal Jastrzebski #include <inttypes.h>
16cc7e8ae8SMichal Jastrzebski #include <getopt.h>
17cc7e8ae8SMichal Jastrzebski #include <termios.h>
18cc7e8ae8SMichal Jastrzebski #include <unistd.h>
19cc7e8ae8SMichal Jastrzebski #include <pthread.h>
20cc7e8ae8SMichal Jastrzebski 
21cc7e8ae8SMichal Jastrzebski #include <rte_common.h>
22cc7e8ae8SMichal Jastrzebski #include <rte_log.h>
23cc7e8ae8SMichal Jastrzebski #include <rte_memory.h>
24cc7e8ae8SMichal Jastrzebski #include <rte_memcpy.h>
25cc7e8ae8SMichal Jastrzebski #include <rte_eal.h>
26cc7e8ae8SMichal Jastrzebski #include <rte_launch.h>
27cc7e8ae8SMichal Jastrzebski #include <rte_atomic.h>
28cc7e8ae8SMichal Jastrzebski #include <rte_cycles.h>
29cc7e8ae8SMichal Jastrzebski #include <rte_prefetch.h>
30cc7e8ae8SMichal Jastrzebski #include <rte_lcore.h>
31cc7e8ae8SMichal Jastrzebski #include <rte_per_lcore.h>
32cc7e8ae8SMichal Jastrzebski #include <rte_branch_prediction.h>
33cc7e8ae8SMichal Jastrzebski #include <rte_interrupts.h>
34cc7e8ae8SMichal Jastrzebski #include <rte_random.h>
35cc7e8ae8SMichal Jastrzebski #include <rte_debug.h>
36cc7e8ae8SMichal Jastrzebski #include <rte_ether.h>
37cc7e8ae8SMichal Jastrzebski #include <rte_ethdev.h>
38cc7e8ae8SMichal Jastrzebski #include <rte_mempool.h>
39cc7e8ae8SMichal Jastrzebski #include <rte_mbuf.h>
40cc7e8ae8SMichal Jastrzebski #include <rte_ip.h>
41cc7e8ae8SMichal Jastrzebski #include <rte_tcp.h>
42cc7e8ae8SMichal Jastrzebski #include <rte_arp.h>
43cc7e8ae8SMichal Jastrzebski #include <rte_spinlock.h>
44cc7e8ae8SMichal Jastrzebski 
45cc7e8ae8SMichal Jastrzebski #include <cmdline_rdline.h>
46cc7e8ae8SMichal Jastrzebski #include <cmdline_parse.h>
47cc7e8ae8SMichal Jastrzebski #include <cmdline_parse_num.h>
48cc7e8ae8SMichal Jastrzebski #include <cmdline_parse_string.h>
49cc7e8ae8SMichal Jastrzebski #include <cmdline_parse_ipaddr.h>
50cc7e8ae8SMichal Jastrzebski #include <cmdline_parse_etheraddr.h>
51cc7e8ae8SMichal Jastrzebski #include <cmdline_socket.h>
52cc7e8ae8SMichal Jastrzebski #include <cmdline.h>
53cc7e8ae8SMichal Jastrzebski 
54cc7e8ae8SMichal Jastrzebski #include "main.h"
55cc7e8ae8SMichal Jastrzebski 
56cc7e8ae8SMichal Jastrzebski #include <rte_devargs.h>
57cc7e8ae8SMichal Jastrzebski 
58cc7e8ae8SMichal Jastrzebski 
59cc7e8ae8SMichal Jastrzebski #include "rte_byteorder.h"
60cc7e8ae8SMichal Jastrzebski #include "rte_cpuflags.h"
61cc7e8ae8SMichal Jastrzebski #include "rte_eth_bond.h"
62cc7e8ae8SMichal Jastrzebski 
63cc7e8ae8SMichal Jastrzebski #define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1
64cc7e8ae8SMichal Jastrzebski 
65cc7e8ae8SMichal Jastrzebski #define NB_MBUF   (1024*8)
66cc7e8ae8SMichal Jastrzebski 
67cc7e8ae8SMichal Jastrzebski #define MAX_PKT_BURST 32
68cc7e8ae8SMichal Jastrzebski #define BURST_TX_DRAIN_US 100      /* TX drain every ~100us */
69cc7e8ae8SMichal Jastrzebski #define BURST_RX_INTERVAL_NS (10) /* RX poll interval ~100ns */
70cc7e8ae8SMichal Jastrzebski 
71cc7e8ae8SMichal Jastrzebski /*
72cc7e8ae8SMichal Jastrzebski  * RX and TX Prefetch, Host, and Write-back threshold values should be
73cc7e8ae8SMichal Jastrzebski  * carefully set for optimal performance. Consult the network
74cc7e8ae8SMichal Jastrzebski  * controller's datasheet and supporting DPDK documentation for guidance
75cc7e8ae8SMichal Jastrzebski  * on how these parameters should be set.
76cc7e8ae8SMichal Jastrzebski  */
77cc7e8ae8SMichal Jastrzebski #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
78cc7e8ae8SMichal Jastrzebski #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
79cc7e8ae8SMichal Jastrzebski #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
80cc7e8ae8SMichal Jastrzebski #define RX_FTHRESH (MAX_PKT_BURST * 2)/**< Default values of RX free threshold reg. */
81cc7e8ae8SMichal Jastrzebski 
82cc7e8ae8SMichal Jastrzebski /*
83cc7e8ae8SMichal Jastrzebski  * These default values are optimized for use with the Intel(R) 82599 10 GbE
84cc7e8ae8SMichal Jastrzebski  * Controller and the DPDK ixgbe PMD. Consider using other values for other
85cc7e8ae8SMichal Jastrzebski  * network controllers and/or network drivers.
86cc7e8ae8SMichal Jastrzebski  */
87cc7e8ae8SMichal Jastrzebski #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
88cc7e8ae8SMichal Jastrzebski #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
89cc7e8ae8SMichal Jastrzebski #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
90cc7e8ae8SMichal Jastrzebski 
91cc7e8ae8SMichal Jastrzebski /*
92cc7e8ae8SMichal Jastrzebski  * Configurable number of RX/TX ring descriptors
93cc7e8ae8SMichal Jastrzebski  */
94867a6c66SKevin Laatz #define RTE_RX_DESC_DEFAULT 1024
95867a6c66SKevin Laatz #define RTE_TX_DESC_DEFAULT 1024
96cc7e8ae8SMichal Jastrzebski 
97cc7e8ae8SMichal Jastrzebski #define BOND_IP_1	7
98cc7e8ae8SMichal Jastrzebski #define BOND_IP_2	0
99cc7e8ae8SMichal Jastrzebski #define BOND_IP_3	0
100cc7e8ae8SMichal Jastrzebski #define BOND_IP_4	10
101cc7e8ae8SMichal Jastrzebski 
102cc7e8ae8SMichal Jastrzebski /* not defined under linux */
103cc7e8ae8SMichal Jastrzebski #ifndef NIPQUAD
104cc7e8ae8SMichal Jastrzebski #define NIPQUAD_FMT "%u.%u.%u.%u"
105cc7e8ae8SMichal Jastrzebski #endif
106cc7e8ae8SMichal Jastrzebski 
107cc7e8ae8SMichal Jastrzebski #define MAX_PORTS	4
108cc7e8ae8SMichal Jastrzebski #define PRINT_MAC(addr)		printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \
109cc7e8ae8SMichal Jastrzebski 		":%02"PRIx8":%02"PRIx8":%02"PRIx8,	\
110cc7e8ae8SMichal Jastrzebski 		addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], \
111cc7e8ae8SMichal Jastrzebski 		addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5])
112cc7e8ae8SMichal Jastrzebski 
113f8244c63SZhiyong Yang uint16_t slaves[RTE_MAX_ETHPORTS];
114f8244c63SZhiyong Yang uint16_t slaves_count;
115cc7e8ae8SMichal Jastrzebski 
116f8244c63SZhiyong Yang static uint16_t BOND_PORT = 0xffff;
117cc7e8ae8SMichal Jastrzebski 
118cc7e8ae8SMichal Jastrzebski static struct rte_mempool *mbuf_pool;
119cc7e8ae8SMichal Jastrzebski 
120cc7e8ae8SMichal Jastrzebski static struct rte_eth_conf port_conf = {
121cc7e8ae8SMichal Jastrzebski 	.rxmode = {
122cc7e8ae8SMichal Jastrzebski 		.mq_mode = ETH_MQ_RX_NONE,
12335b2d13fSOlivier Matz 		.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
124cc7e8ae8SMichal Jastrzebski 		.split_hdr_size = 0,
125cc7e8ae8SMichal Jastrzebski 	},
126cc7e8ae8SMichal Jastrzebski 	.rx_adv_conf = {
127cc7e8ae8SMichal Jastrzebski 		.rss_conf = {
128cc7e8ae8SMichal Jastrzebski 			.rss_key = NULL,
129cc7e8ae8SMichal Jastrzebski 			.rss_hf = ETH_RSS_IP,
130cc7e8ae8SMichal Jastrzebski 		},
131cc7e8ae8SMichal Jastrzebski 	},
132cc7e8ae8SMichal Jastrzebski 	.txmode = {
133cc7e8ae8SMichal Jastrzebski 		.mq_mode = ETH_MQ_TX_NONE,
134cc7e8ae8SMichal Jastrzebski 	},
135cc7e8ae8SMichal Jastrzebski };
136cc7e8ae8SMichal Jastrzebski 
137cc7e8ae8SMichal Jastrzebski static void
138f8244c63SZhiyong Yang slave_port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
139cc7e8ae8SMichal Jastrzebski {
140cc7e8ae8SMichal Jastrzebski 	int retval;
14160efb44fSRoman Zhukov 	uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
14260efb44fSRoman Zhukov 	uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
143c1b77788SShahaf Shuler 	struct rte_eth_dev_info dev_info;
144c1b77788SShahaf Shuler 	struct rte_eth_rxconf rxq_conf;
145c1b77788SShahaf Shuler 	struct rte_eth_txconf txq_conf;
146c1b77788SShahaf Shuler 	struct rte_eth_conf local_port_conf = port_conf;
147cc7e8ae8SMichal Jastrzebski 
148a9dbe180SThomas Monjalon 	if (!rte_eth_dev_is_valid_port(portid))
149cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Invalid port\n");
150cc7e8ae8SMichal Jastrzebski 
151*089e5ed7SIvan Ilchenko 	retval = rte_eth_dev_info_get(portid, &dev_info);
152*089e5ed7SIvan Ilchenko 	if (retval != 0)
153*089e5ed7SIvan Ilchenko 		rte_exit(EXIT_FAILURE,
154*089e5ed7SIvan Ilchenko 			"Error during getting device (port %u) info: %s\n",
155*089e5ed7SIvan Ilchenko 			portid, strerror(-retval));
156*089e5ed7SIvan Ilchenko 
157c1b77788SShahaf Shuler 	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
158c1b77788SShahaf Shuler 		local_port_conf.txmode.offloads |=
159c1b77788SShahaf Shuler 			DEV_TX_OFFLOAD_MBUF_FAST_FREE;
1604f5701f2SFerruh Yigit 
1614f5701f2SFerruh Yigit 	local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
1624f5701f2SFerruh Yigit 		dev_info.flow_type_rss_offloads;
1634f5701f2SFerruh Yigit 	if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
1644f5701f2SFerruh Yigit 			port_conf.rx_adv_conf.rss_conf.rss_hf) {
1654f5701f2SFerruh Yigit 		printf("Port %u modified RSS hash function based on hardware support,"
1664f5701f2SFerruh Yigit 			"requested:%#"PRIx64" configured:%#"PRIx64"\n",
1674f5701f2SFerruh Yigit 			portid,
1684f5701f2SFerruh Yigit 			port_conf.rx_adv_conf.rss_conf.rss_hf,
1694f5701f2SFerruh Yigit 			local_port_conf.rx_adv_conf.rss_conf.rss_hf);
1704f5701f2SFerruh Yigit 	}
1714f5701f2SFerruh Yigit 
172c1b77788SShahaf Shuler 	retval = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
173cc7e8ae8SMichal Jastrzebski 	if (retval != 0)
174cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n",
175cc7e8ae8SMichal Jastrzebski 				portid, retval);
176cc7e8ae8SMichal Jastrzebski 
17760efb44fSRoman Zhukov 	retval = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
17860efb44fSRoman Zhukov 	if (retval != 0)
17960efb44fSRoman Zhukov 		rte_exit(EXIT_FAILURE, "port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
18060efb44fSRoman Zhukov 				"failed (res=%d)\n", portid, retval);
18160efb44fSRoman Zhukov 
182cc7e8ae8SMichal Jastrzebski 	/* RX setup */
183c1b77788SShahaf Shuler 	rxq_conf = dev_info.default_rxconf;
184c1b77788SShahaf Shuler 	rxq_conf.offloads = local_port_conf.rxmode.offloads;
18560efb44fSRoman Zhukov 	retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
186c1b77788SShahaf Shuler 					rte_eth_dev_socket_id(portid),
187c1b77788SShahaf Shuler 					&rxq_conf,
188cc7e8ae8SMichal Jastrzebski 					mbuf_pool);
189cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
190cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)",
191cc7e8ae8SMichal Jastrzebski 				portid, retval);
192cc7e8ae8SMichal Jastrzebski 
193cc7e8ae8SMichal Jastrzebski 	/* TX setup */
194c1b77788SShahaf Shuler 	txq_conf = dev_info.default_txconf;
195c1b77788SShahaf Shuler 	txq_conf.offloads = local_port_conf.txmode.offloads;
19660efb44fSRoman Zhukov 	retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
197c1b77788SShahaf Shuler 				rte_eth_dev_socket_id(portid), &txq_conf);
198cc7e8ae8SMichal Jastrzebski 
199cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
200cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)",
201cc7e8ae8SMichal Jastrzebski 				portid, retval);
202cc7e8ae8SMichal Jastrzebski 
203cc7e8ae8SMichal Jastrzebski 	retval  = rte_eth_dev_start(portid);
204cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
205cc7e8ae8SMichal Jastrzebski 		rte_exit(retval,
206cc7e8ae8SMichal Jastrzebski 				"Start port %d failed (res=%d)",
207cc7e8ae8SMichal Jastrzebski 				portid, retval);
208cc7e8ae8SMichal Jastrzebski 
2096d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
210cc7e8ae8SMichal Jastrzebski 
211cc7e8ae8SMichal Jastrzebski 	rte_eth_macaddr_get(portid, &addr);
212f8244c63SZhiyong Yang 	printf("Port %u MAC: ", portid);
213cc7e8ae8SMichal Jastrzebski 	PRINT_MAC(addr);
214cc7e8ae8SMichal Jastrzebski 	printf("\n");
215cc7e8ae8SMichal Jastrzebski }
216cc7e8ae8SMichal Jastrzebski 
217cc7e8ae8SMichal Jastrzebski static void
218cc7e8ae8SMichal Jastrzebski bond_port_init(struct rte_mempool *mbuf_pool)
219cc7e8ae8SMichal Jastrzebski {
220cc7e8ae8SMichal Jastrzebski 	int retval;
221cc7e8ae8SMichal Jastrzebski 	uint8_t i;
22260efb44fSRoman Zhukov 	uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
22360efb44fSRoman Zhukov 	uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
224c1b77788SShahaf Shuler 	struct rte_eth_dev_info dev_info;
225c1b77788SShahaf Shuler 	struct rte_eth_rxconf rxq_conf;
226c1b77788SShahaf Shuler 	struct rte_eth_txconf txq_conf;
227c1b77788SShahaf Shuler 	struct rte_eth_conf local_port_conf = port_conf;
228292fdb76SRadu Nicolau 	uint16_t wait_counter = 20;
229cc7e8ae8SMichal Jastrzebski 
230e6509c6cSRadu Nicolau 	retval = rte_eth_bond_create("net_bonding0", BONDING_MODE_ALB,
231cc7e8ae8SMichal Jastrzebski 			0 /*SOCKET_ID_ANY*/);
232cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
233cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE,
234cc7e8ae8SMichal Jastrzebski 				"Faled to create bond port\n");
235cc7e8ae8SMichal Jastrzebski 
236f8244c63SZhiyong Yang 	BOND_PORT = retval;
237cc7e8ae8SMichal Jastrzebski 
238*089e5ed7SIvan Ilchenko 	retval = rte_eth_dev_info_get(BOND_PORT, &dev_info);
239*089e5ed7SIvan Ilchenko 	if (retval != 0)
240*089e5ed7SIvan Ilchenko 		rte_exit(EXIT_FAILURE,
241*089e5ed7SIvan Ilchenko 			"Error during getting device (port %u) info: %s\n",
242*089e5ed7SIvan Ilchenko 			BOND_PORT, strerror(-retval));
243*089e5ed7SIvan Ilchenko 
244c1b77788SShahaf Shuler 	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
245c1b77788SShahaf Shuler 		local_port_conf.txmode.offloads |=
246c1b77788SShahaf Shuler 			DEV_TX_OFFLOAD_MBUF_FAST_FREE;
247c1b77788SShahaf Shuler 	retval = rte_eth_dev_configure(BOND_PORT, 1, 1, &local_port_conf);
248cc7e8ae8SMichal Jastrzebski 	if (retval != 0)
249cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n",
250cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
251cc7e8ae8SMichal Jastrzebski 
25260efb44fSRoman Zhukov 	retval = rte_eth_dev_adjust_nb_rx_tx_desc(BOND_PORT, &nb_rxd, &nb_txd);
25360efb44fSRoman Zhukov 	if (retval != 0)
25460efb44fSRoman Zhukov 		rte_exit(EXIT_FAILURE, "port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
25560efb44fSRoman Zhukov 				"failed (res=%d)\n", BOND_PORT, retval);
25660efb44fSRoman Zhukov 
2572eee509cSRadu Nicolau 	for (i = 0; i < slaves_count; i++) {
2582eee509cSRadu Nicolau 		if (rte_eth_bond_slave_add(BOND_PORT, slaves[i]) == -1)
2592eee509cSRadu Nicolau 			rte_exit(-1, "Oooops! adding slave (%u) to bond (%u) failed!\n",
2602eee509cSRadu Nicolau 					slaves[i], BOND_PORT);
2612eee509cSRadu Nicolau 
2622eee509cSRadu Nicolau 	}
2632eee509cSRadu Nicolau 
264cc7e8ae8SMichal Jastrzebski 	/* RX setup */
265c1b77788SShahaf Shuler 	rxq_conf = dev_info.default_rxconf;
266c1b77788SShahaf Shuler 	rxq_conf.offloads = local_port_conf.rxmode.offloads;
26760efb44fSRoman Zhukov 	retval = rte_eth_rx_queue_setup(BOND_PORT, 0, nb_rxd,
268c1b77788SShahaf Shuler 					rte_eth_dev_socket_id(BOND_PORT),
269c1b77788SShahaf Shuler 					&rxq_conf, mbuf_pool);
270cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
271cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)",
272cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
273cc7e8ae8SMichal Jastrzebski 
274cc7e8ae8SMichal Jastrzebski 	/* TX setup */
275c1b77788SShahaf Shuler 	txq_conf = dev_info.default_txconf;
276c1b77788SShahaf Shuler 	txq_conf.offloads = local_port_conf.txmode.offloads;
27760efb44fSRoman Zhukov 	retval = rte_eth_tx_queue_setup(BOND_PORT, 0, nb_txd,
278c1b77788SShahaf Shuler 				rte_eth_dev_socket_id(BOND_PORT), &txq_conf);
279cc7e8ae8SMichal Jastrzebski 
280cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
281cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)",
282cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
283cc7e8ae8SMichal Jastrzebski 
284cc7e8ae8SMichal Jastrzebski 	retval  = rte_eth_dev_start(BOND_PORT);
285cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
286cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "Start port %d failed (res=%d)", BOND_PORT, retval);
287cc7e8ae8SMichal Jastrzebski 
288292fdb76SRadu Nicolau 	printf("Waiting for slaves to become active...");
289292fdb76SRadu Nicolau 	while (wait_counter) {
290292fdb76SRadu Nicolau 		uint16_t act_slaves[16] = {0};
291292fdb76SRadu Nicolau 		if (rte_eth_bond_active_slaves_get(BOND_PORT, act_slaves, 16) ==
292292fdb76SRadu Nicolau 				slaves_count) {
293292fdb76SRadu Nicolau 			printf("\n");
294292fdb76SRadu Nicolau 			break;
295292fdb76SRadu Nicolau 		}
296292fdb76SRadu Nicolau 		sleep(1);
297292fdb76SRadu Nicolau 		printf("...");
298292fdb76SRadu Nicolau 		if (--wait_counter == 0)
299292fdb76SRadu Nicolau 			rte_exit(-1, "\nFailed to activate slaves\n");
300292fdb76SRadu Nicolau 	}
301292fdb76SRadu Nicolau 
302cc7e8ae8SMichal Jastrzebski 	rte_eth_promiscuous_enable(BOND_PORT);
303cc7e8ae8SMichal Jastrzebski 
3046d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
305cc7e8ae8SMichal Jastrzebski 
306cc7e8ae8SMichal Jastrzebski 	rte_eth_macaddr_get(BOND_PORT, &addr);
307cc7e8ae8SMichal Jastrzebski 	printf("Port %u MAC: ", (unsigned)BOND_PORT);
308cc7e8ae8SMichal Jastrzebski 		PRINT_MAC(addr);
309cc7e8ae8SMichal Jastrzebski 		printf("\n");
310cc7e8ae8SMichal Jastrzebski }
311cc7e8ae8SMichal Jastrzebski 
312cc7e8ae8SMichal Jastrzebski static inline size_t
3136d13ea8eSOlivier Matz get_vlan_offset(struct rte_ether_hdr *eth_hdr, uint16_t *proto)
314cc7e8ae8SMichal Jastrzebski {
315cc7e8ae8SMichal Jastrzebski 	size_t vlan_offset = 0;
316cc7e8ae8SMichal Jastrzebski 
31735b2d13fSOlivier Matz 	if (rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) == *proto) {
3186d13ea8eSOlivier Matz 		struct rte_vlan_hdr *vlan_hdr =
3196d13ea8eSOlivier Matz 			(struct rte_vlan_hdr *)(eth_hdr + 1);
320cc7e8ae8SMichal Jastrzebski 
3216d13ea8eSOlivier Matz 		vlan_offset = sizeof(struct rte_vlan_hdr);
322cc7e8ae8SMichal Jastrzebski 		*proto = vlan_hdr->eth_proto;
323cc7e8ae8SMichal Jastrzebski 
32435b2d13fSOlivier Matz 		if (rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) == *proto) {
325cc7e8ae8SMichal Jastrzebski 			vlan_hdr = vlan_hdr + 1;
326cc7e8ae8SMichal Jastrzebski 
327cc7e8ae8SMichal Jastrzebski 			*proto = vlan_hdr->eth_proto;
3286d13ea8eSOlivier Matz 			vlan_offset += sizeof(struct rte_vlan_hdr);
329cc7e8ae8SMichal Jastrzebski 		}
330cc7e8ae8SMichal Jastrzebski 	}
331cc7e8ae8SMichal Jastrzebski 	return vlan_offset;
332cc7e8ae8SMichal Jastrzebski }
333cc7e8ae8SMichal Jastrzebski 
334cc7e8ae8SMichal Jastrzebski struct global_flag_stru_t {
335cc7e8ae8SMichal Jastrzebski 	int LcoreMainIsRunning;
336cc7e8ae8SMichal Jastrzebski 	int LcoreMainCore;
337cc7e8ae8SMichal Jastrzebski 	uint32_t port_packets[4];
338cc7e8ae8SMichal Jastrzebski 	rte_spinlock_t lock;
339cc7e8ae8SMichal Jastrzebski };
340cc7e8ae8SMichal Jastrzebski struct global_flag_stru_t global_flag_stru;
341cc7e8ae8SMichal Jastrzebski struct global_flag_stru_t *global_flag_stru_p = &global_flag_stru;
342cc7e8ae8SMichal Jastrzebski 
343cc7e8ae8SMichal Jastrzebski /*
344cc7e8ae8SMichal Jastrzebski  * Main thread that does the work, reading from INPUT_PORT
345cc7e8ae8SMichal Jastrzebski  * and writing to OUTPUT_PORT
346cc7e8ae8SMichal Jastrzebski  */
347cc7e8ae8SMichal Jastrzebski static int lcore_main(__attribute__((unused)) void *arg1)
348cc7e8ae8SMichal Jastrzebski {
349cc7e8ae8SMichal Jastrzebski 	struct rte_mbuf *pkts[MAX_PKT_BURST] __rte_cache_aligned;
3506d13ea8eSOlivier Matz 	struct rte_ether_addr d_addr;
351cc7e8ae8SMichal Jastrzebski 
3526d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
353f2745bfeSOlivier Matz 	struct rte_arp_hdr *arp_hdr;
354a7c528e5SOlivier Matz 	struct rte_ipv4_hdr *ipv4_hdr;
355cc7e8ae8SMichal Jastrzebski 	uint16_t ether_type, offset;
356cc7e8ae8SMichal Jastrzebski 
357cc7e8ae8SMichal Jastrzebski 	uint16_t rx_cnt;
358cc7e8ae8SMichal Jastrzebski 	uint32_t bond_ip;
359cc7e8ae8SMichal Jastrzebski 	int i = 0;
360cc7e8ae8SMichal Jastrzebski 	uint8_t is_free;
361cc7e8ae8SMichal Jastrzebski 
362cc7e8ae8SMichal Jastrzebski 	bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
363cc7e8ae8SMichal Jastrzebski 				(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
364cc7e8ae8SMichal Jastrzebski 
365cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
366cc7e8ae8SMichal Jastrzebski 
367cc7e8ae8SMichal Jastrzebski 	while (global_flag_stru_p->LcoreMainIsRunning) {
368cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
369cc7e8ae8SMichal Jastrzebski 		rx_cnt = rte_eth_rx_burst(BOND_PORT, 0, pkts, MAX_PKT_BURST);
370cc7e8ae8SMichal Jastrzebski 		is_free = 0;
371cc7e8ae8SMichal Jastrzebski 
372cc7e8ae8SMichal Jastrzebski 		/* If didn't receive any packets, wait and go to next iteration */
373cc7e8ae8SMichal Jastrzebski 		if (rx_cnt == 0) {
374cc7e8ae8SMichal Jastrzebski 			rte_delay_us(50);
375cc7e8ae8SMichal Jastrzebski 			continue;
376cc7e8ae8SMichal Jastrzebski 		}
377cc7e8ae8SMichal Jastrzebski 
378cc7e8ae8SMichal Jastrzebski 		/* Search incoming data for ARP packets and prepare response */
379cc7e8ae8SMichal Jastrzebski 		for (i = 0; i < rx_cnt; i++) {
380cc7e8ae8SMichal Jastrzebski 			if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1) {
381cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->port_packets[0]++;
382cc7e8ae8SMichal Jastrzebski 				rte_spinlock_unlock(&global_flag_stru_p->lock);
383cc7e8ae8SMichal Jastrzebski 			}
3846d13ea8eSOlivier Matz 			eth_hdr = rte_pktmbuf_mtod(pkts[i],
3856d13ea8eSOlivier Matz 						struct rte_ether_hdr *);
386cc7e8ae8SMichal Jastrzebski 			ether_type = eth_hdr->ether_type;
38735b2d13fSOlivier Matz 			if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN))
388cc7e8ae8SMichal Jastrzebski 				printf("VLAN taged frame, offset:");
389cc7e8ae8SMichal Jastrzebski 			offset = get_vlan_offset(eth_hdr, &ether_type);
390cc7e8ae8SMichal Jastrzebski 			if (offset > 0)
391cc7e8ae8SMichal Jastrzebski 				printf("%d\n", offset);
39235b2d13fSOlivier Matz 			if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
393cc7e8ae8SMichal Jastrzebski 				if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1)     {
394cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->port_packets[1]++;
395cc7e8ae8SMichal Jastrzebski 					rte_spinlock_unlock(&global_flag_stru_p->lock);
396cc7e8ae8SMichal Jastrzebski 				}
397f2745bfeSOlivier Matz 				arp_hdr = (struct rte_arp_hdr *)(
398f2745bfeSOlivier Matz 					(char *)(eth_hdr + 1) + offset);
399cc7e8ae8SMichal Jastrzebski 				if (arp_hdr->arp_data.arp_tip == bond_ip) {
400e482e0faSOlivier Matz 					if (arp_hdr->arp_opcode == rte_cpu_to_be_16(RTE_ARP_OP_REQUEST)) {
401e482e0faSOlivier Matz 						arp_hdr->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
402cc7e8ae8SMichal Jastrzebski 						/* Switch src and dst data and set bonding MAC */
403538da7a1SOlivier Matz 						rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
404cc7e8ae8SMichal Jastrzebski 						rte_eth_macaddr_get(BOND_PORT, &eth_hdr->s_addr);
405538da7a1SOlivier Matz 						rte_ether_addr_copy(&arp_hdr->arp_data.arp_sha,
406538da7a1SOlivier Matz 								&arp_hdr->arp_data.arp_tha);
407cc7e8ae8SMichal Jastrzebski 						arp_hdr->arp_data.arp_tip = arp_hdr->arp_data.arp_sip;
408cc7e8ae8SMichal Jastrzebski 						rte_eth_macaddr_get(BOND_PORT, &d_addr);
409538da7a1SOlivier Matz 						rte_ether_addr_copy(&d_addr, &arp_hdr->arp_data.arp_sha);
410cc7e8ae8SMichal Jastrzebski 						arp_hdr->arp_data.arp_sip = bond_ip;
411cc7e8ae8SMichal Jastrzebski 						rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1);
412cc7e8ae8SMichal Jastrzebski 						is_free = 1;
413cc7e8ae8SMichal Jastrzebski 					} else {
414cc7e8ae8SMichal Jastrzebski 						rte_eth_tx_burst(BOND_PORT, 0, NULL, 0);
415cc7e8ae8SMichal Jastrzebski 					}
416cc7e8ae8SMichal Jastrzebski 				}
4170c9da755SDavid Marchand 			} else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
418cc7e8ae8SMichal Jastrzebski 				if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1)     {
419cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->port_packets[2]++;
420cc7e8ae8SMichal Jastrzebski 					rte_spinlock_unlock(&global_flag_stru_p->lock);
421cc7e8ae8SMichal Jastrzebski 				 }
422a7c528e5SOlivier Matz 				ipv4_hdr = (struct rte_ipv4_hdr *)((char *)(eth_hdr + 1) + offset);
423cc7e8ae8SMichal Jastrzebski 				if (ipv4_hdr->dst_addr == bond_ip) {
424538da7a1SOlivier Matz 					rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
425cc7e8ae8SMichal Jastrzebski 					rte_eth_macaddr_get(BOND_PORT, &eth_hdr->s_addr);
426cc7e8ae8SMichal Jastrzebski 					ipv4_hdr->dst_addr = ipv4_hdr->src_addr;
427cc7e8ae8SMichal Jastrzebski 					ipv4_hdr->src_addr = bond_ip;
428cc7e8ae8SMichal Jastrzebski 					rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1);
429cc7e8ae8SMichal Jastrzebski 				}
430cc7e8ae8SMichal Jastrzebski 
431cc7e8ae8SMichal Jastrzebski 			}
432cc7e8ae8SMichal Jastrzebski 
433cc7e8ae8SMichal Jastrzebski 			/* Free processed packets */
434cc7e8ae8SMichal Jastrzebski 			if (is_free == 0)
435cc7e8ae8SMichal Jastrzebski 				rte_pktmbuf_free(pkts[i]);
436cc7e8ae8SMichal Jastrzebski 		}
437cc7e8ae8SMichal Jastrzebski 		rte_spinlock_trylock(&global_flag_stru_p->lock);
438cc7e8ae8SMichal Jastrzebski 	}
439cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
440cc7e8ae8SMichal Jastrzebski 	printf("BYE lcore_main\n");
441cc7e8ae8SMichal Jastrzebski 	return 0;
442cc7e8ae8SMichal Jastrzebski }
443cc7e8ae8SMichal Jastrzebski 
444cc7e8ae8SMichal Jastrzebski struct cmd_obj_send_result {
445cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t action;
446cc7e8ae8SMichal Jastrzebski 	cmdline_ipaddr_t ip;
447cc7e8ae8SMichal Jastrzebski };
448cc7e8ae8SMichal Jastrzebski static inline void get_string(struct cmd_obj_send_result *res, char *buf, uint8_t size)
449cc7e8ae8SMichal Jastrzebski {
450cc7e8ae8SMichal Jastrzebski 	snprintf(buf, size, NIPQUAD_FMT,
451cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[0]),
452cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[1]),
453cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[2]),
454cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[3])
455cc7e8ae8SMichal Jastrzebski 		);
456cc7e8ae8SMichal Jastrzebski }
457cc7e8ae8SMichal Jastrzebski static void cmd_obj_send_parsed(void *parsed_result,
458cc7e8ae8SMichal Jastrzebski 		__attribute__((unused)) struct cmdline *cl,
459cc7e8ae8SMichal Jastrzebski 			       __attribute__((unused)) void *data)
460cc7e8ae8SMichal Jastrzebski {
461cc7e8ae8SMichal Jastrzebski 
462cc7e8ae8SMichal Jastrzebski 	struct cmd_obj_send_result *res = parsed_result;
463cc7e8ae8SMichal Jastrzebski 	char ip_str[INET6_ADDRSTRLEN];
464cc7e8ae8SMichal Jastrzebski 
465cc7e8ae8SMichal Jastrzebski 	struct rte_mbuf *created_pkt;
4666d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
467f2745bfeSOlivier Matz 	struct rte_arp_hdr *arp_hdr;
468cc7e8ae8SMichal Jastrzebski 
469cc7e8ae8SMichal Jastrzebski 	uint32_t bond_ip;
470cc7e8ae8SMichal Jastrzebski 	size_t pkt_size;
471cc7e8ae8SMichal Jastrzebski 
472cc7e8ae8SMichal Jastrzebski 	if (res->ip.family == AF_INET)
473cc7e8ae8SMichal Jastrzebski 		get_string(res, ip_str, INET_ADDRSTRLEN);
474cc7e8ae8SMichal Jastrzebski 	else
475cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl, "Wrong IP format. Only IPv4 is supported\n");
476cc7e8ae8SMichal Jastrzebski 
477cc7e8ae8SMichal Jastrzebski 	bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
478cc7e8ae8SMichal Jastrzebski 				(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
479cc7e8ae8SMichal Jastrzebski 
480cc7e8ae8SMichal Jastrzebski 	created_pkt = rte_pktmbuf_alloc(mbuf_pool);
4810bb76fc9SRadu Nicolau 	if (created_pkt == NULL) {
4820bb76fc9SRadu Nicolau 		cmdline_printf(cl, "Failed to allocate mbuf\n");
4830bb76fc9SRadu Nicolau 		return;
4840bb76fc9SRadu Nicolau 	}
4850bb76fc9SRadu Nicolau 
4866d13ea8eSOlivier Matz 	pkt_size = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);
487cc7e8ae8SMichal Jastrzebski 	created_pkt->data_len = pkt_size;
488cc7e8ae8SMichal Jastrzebski 	created_pkt->pkt_len = pkt_size;
489cc7e8ae8SMichal Jastrzebski 
4906d13ea8eSOlivier Matz 	eth_hdr = rte_pktmbuf_mtod(created_pkt, struct rte_ether_hdr *);
491cc7e8ae8SMichal Jastrzebski 	rte_eth_macaddr_get(BOND_PORT, &eth_hdr->s_addr);
49235b2d13fSOlivier Matz 	memset(&eth_hdr->d_addr, 0xFF, RTE_ETHER_ADDR_LEN);
49335b2d13fSOlivier Matz 	eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
494cc7e8ae8SMichal Jastrzebski 
495f2745bfeSOlivier Matz 	arp_hdr = (struct rte_arp_hdr *)(
4966d13ea8eSOlivier Matz 		(char *)eth_hdr + sizeof(struct rte_ether_hdr));
497e482e0faSOlivier Matz 	arp_hdr->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
4980c9da755SDavid Marchand 	arp_hdr->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
49935b2d13fSOlivier Matz 	arp_hdr->arp_hlen = RTE_ETHER_ADDR_LEN;
500f2745bfeSOlivier Matz 	arp_hdr->arp_plen = sizeof(uint32_t);
501e482e0faSOlivier Matz 	arp_hdr->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REQUEST);
502cc7e8ae8SMichal Jastrzebski 
503cc7e8ae8SMichal Jastrzebski 	rte_eth_macaddr_get(BOND_PORT, &arp_hdr->arp_data.arp_sha);
504cc7e8ae8SMichal Jastrzebski 	arp_hdr->arp_data.arp_sip = bond_ip;
50535b2d13fSOlivier Matz 	memset(&arp_hdr->arp_data.arp_tha, 0, RTE_ETHER_ADDR_LEN);
506cc7e8ae8SMichal Jastrzebski 	arp_hdr->arp_data.arp_tip =
507cc7e8ae8SMichal Jastrzebski 			  ((unsigned char *)&res->ip.addr.ipv4)[0]        |
508cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[1] << 8)  |
509cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[2] << 16) |
510cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[3] << 24);
511cc7e8ae8SMichal Jastrzebski 	rte_eth_tx_burst(BOND_PORT, 0, &created_pkt, 1);
512cc7e8ae8SMichal Jastrzebski 
513cc7e8ae8SMichal Jastrzebski 	rte_delay_ms(100);
514cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl, "\n");
515cc7e8ae8SMichal Jastrzebski }
516cc7e8ae8SMichal Jastrzebski 
517cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_obj_action_send =
518cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result, action, "send");
519cc7e8ae8SMichal Jastrzebski cmdline_parse_token_ipaddr_t cmd_obj_ip =
520cc7e8ae8SMichal Jastrzebski 	TOKEN_IPV4_INITIALIZER(struct cmd_obj_send_result, ip);
521cc7e8ae8SMichal Jastrzebski 
522cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_obj_send = {
523cc7e8ae8SMichal Jastrzebski 	.f = cmd_obj_send_parsed,  /* function to call */
524cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
525cc7e8ae8SMichal Jastrzebski 	.help_str = "send client_ip",
526cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
527cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_obj_action_send,
528cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_obj_ip,
529cc7e8ae8SMichal Jastrzebski 		NULL,
530cc7e8ae8SMichal Jastrzebski 	},
531cc7e8ae8SMichal Jastrzebski };
532cc7e8ae8SMichal Jastrzebski 
533cc7e8ae8SMichal Jastrzebski struct cmd_start_result {
534cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t start;
535cc7e8ae8SMichal Jastrzebski };
536cc7e8ae8SMichal Jastrzebski 
537cc7e8ae8SMichal Jastrzebski static void cmd_start_parsed(__attribute__((unused)) void *parsed_result,
538cc7e8ae8SMichal Jastrzebski 			       struct cmdline *cl,
539cc7e8ae8SMichal Jastrzebski 			       __attribute__((unused)) void *data)
540cc7e8ae8SMichal Jastrzebski {
541cc7e8ae8SMichal Jastrzebski 	int slave_core_id = rte_lcore_id();
542cc7e8ae8SMichal Jastrzebski 
543cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
544cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0) {
5452b7a03c5SStephen Hemminger 		if (rte_eal_get_lcore_state(global_flag_stru_p->LcoreMainCore)
5462b7a03c5SStephen Hemminger 		    != WAIT) {
547cc7e8ae8SMichal Jastrzebski 			rte_spinlock_unlock(&global_flag_stru_p->lock);
548cc7e8ae8SMichal Jastrzebski 			return;
549cc7e8ae8SMichal Jastrzebski 		}
550cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
551cc7e8ae8SMichal Jastrzebski 	} else {
552cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl, "lcore_main already running on core:%d\n",
553cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
554cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
555cc7e8ae8SMichal Jastrzebski 		return;
556cc7e8ae8SMichal Jastrzebski 	}
557cc7e8ae8SMichal Jastrzebski 
558cc7e8ae8SMichal Jastrzebski 	/* start lcore main on core != master_core - ARP response thread */
559cc7e8ae8SMichal Jastrzebski 	slave_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0);
560cc7e8ae8SMichal Jastrzebski 	if ((slave_core_id >= RTE_MAX_LCORE) || (slave_core_id == 0))
561cc7e8ae8SMichal Jastrzebski 		return;
562cc7e8ae8SMichal Jastrzebski 
563cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
564cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 1;
565cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
566cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
567cc7e8ae8SMichal Jastrzebski 			"Starting lcore_main on core %d:%d "
568cc7e8ae8SMichal Jastrzebski 			"Our IP:%d.%d.%d.%d\n",
569cc7e8ae8SMichal Jastrzebski 			slave_core_id,
570cc7e8ae8SMichal Jastrzebski 			rte_eal_remote_launch(lcore_main, NULL, slave_core_id),
571cc7e8ae8SMichal Jastrzebski 			BOND_IP_1,
572cc7e8ae8SMichal Jastrzebski 			BOND_IP_2,
573cc7e8ae8SMichal Jastrzebski 			BOND_IP_3,
574cc7e8ae8SMichal Jastrzebski 			BOND_IP_4
575cc7e8ae8SMichal Jastrzebski 		);
576cc7e8ae8SMichal Jastrzebski }
577cc7e8ae8SMichal Jastrzebski 
578cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_start_start =
579cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start");
580cc7e8ae8SMichal Jastrzebski 
581cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_start = {
582cc7e8ae8SMichal Jastrzebski 	.f = cmd_start_parsed,  /* function to call */
583cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
584cc7e8ae8SMichal Jastrzebski 	.help_str = "starts listening if not started at startup",
585cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
586cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_start_start,
587cc7e8ae8SMichal Jastrzebski 		NULL,
588cc7e8ae8SMichal Jastrzebski 	},
589cc7e8ae8SMichal Jastrzebski };
590cc7e8ae8SMichal Jastrzebski 
591cc7e8ae8SMichal Jastrzebski struct cmd_help_result {
592cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t help;
593cc7e8ae8SMichal Jastrzebski };
594cc7e8ae8SMichal Jastrzebski 
595cc7e8ae8SMichal Jastrzebski static void cmd_help_parsed(__attribute__((unused)) void *parsed_result,
596cc7e8ae8SMichal Jastrzebski 			    struct cmdline *cl,
597cc7e8ae8SMichal Jastrzebski 			    __attribute__((unused)) void *data)
598cc7e8ae8SMichal Jastrzebski {
599cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
600cc7e8ae8SMichal Jastrzebski 			"ALB - link bonding mode 6 example\n"
60198a7ea33SJerin Jacob 			"send IP	- sends one ARPrequest through bonding for IP.\n"
602cc7e8ae8SMichal Jastrzebski 			"start		- starts listening ARPs.\n"
603cc7e8ae8SMichal Jastrzebski 			"stop		- stops lcore_main.\n"
604cc7e8ae8SMichal Jastrzebski 			"show		- shows some bond info: ex. active slaves etc.\n"
605cc7e8ae8SMichal Jastrzebski 			"help		- prints help.\n"
606cc7e8ae8SMichal Jastrzebski 			"quit		- terminate all threads and quit.\n"
607cc7e8ae8SMichal Jastrzebski 		       );
608cc7e8ae8SMichal Jastrzebski }
609cc7e8ae8SMichal Jastrzebski 
610cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_help_help =
611cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");
612cc7e8ae8SMichal Jastrzebski 
613cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_help = {
614cc7e8ae8SMichal Jastrzebski 	.f = cmd_help_parsed,  /* function to call */
615cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
616cc7e8ae8SMichal Jastrzebski 	.help_str = "show help",
617cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
618cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_help_help,
619cc7e8ae8SMichal Jastrzebski 		NULL,
620cc7e8ae8SMichal Jastrzebski 	},
621cc7e8ae8SMichal Jastrzebski };
622cc7e8ae8SMichal Jastrzebski 
623cc7e8ae8SMichal Jastrzebski struct cmd_stop_result {
624cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t stop;
625cc7e8ae8SMichal Jastrzebski };
626cc7e8ae8SMichal Jastrzebski 
627cc7e8ae8SMichal Jastrzebski static void cmd_stop_parsed(__attribute__((unused)) void *parsed_result,
628cc7e8ae8SMichal Jastrzebski 			    struct cmdline *cl,
629cc7e8ae8SMichal Jastrzebski 			    __attribute__((unused)) void *data)
630cc7e8ae8SMichal Jastrzebski {
631cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
632cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0)	{
633cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
634cc7e8ae8SMichal Jastrzebski 					"lcore_main not running on core:%d\n",
635cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->LcoreMainCore);
636cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
637cc7e8ae8SMichal Jastrzebski 		return;
638cc7e8ae8SMichal Jastrzebski 	}
639cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 0;
6403ca530edSPiotr Azarewicz 	if (rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore) < 0)
6413ca530edSPiotr Azarewicz 		cmdline_printf(cl,
6423ca530edSPiotr Azarewicz 				"error: lcore_main can not stop on core:%d\n",
6433ca530edSPiotr Azarewicz 				global_flag_stru_p->LcoreMainCore);
6443ca530edSPiotr Azarewicz 	else
645cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
646cc7e8ae8SMichal Jastrzebski 				"lcore_main stopped on core:%d\n",
647cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
648cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
649cc7e8ae8SMichal Jastrzebski }
650cc7e8ae8SMichal Jastrzebski 
651cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_stop_stop =
652cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop");
653cc7e8ae8SMichal Jastrzebski 
654cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_stop = {
655cc7e8ae8SMichal Jastrzebski 	.f = cmd_stop_parsed,  /* function to call */
656cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
657cc7e8ae8SMichal Jastrzebski 	.help_str = "this command do not handle any arguments",
658cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
659cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_stop_stop,
660cc7e8ae8SMichal Jastrzebski 		NULL,
661cc7e8ae8SMichal Jastrzebski 	},
662cc7e8ae8SMichal Jastrzebski };
663cc7e8ae8SMichal Jastrzebski 
664cc7e8ae8SMichal Jastrzebski struct cmd_quit_result {
665cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t quit;
666cc7e8ae8SMichal Jastrzebski };
667cc7e8ae8SMichal Jastrzebski 
668cc7e8ae8SMichal Jastrzebski static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
669cc7e8ae8SMichal Jastrzebski 			    struct cmdline *cl,
670cc7e8ae8SMichal Jastrzebski 			    __attribute__((unused)) void *data)
671cc7e8ae8SMichal Jastrzebski {
672cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
673cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0)	{
674cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
675cc7e8ae8SMichal Jastrzebski 					"lcore_main not running on core:%d\n",
676cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->LcoreMainCore);
677cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
678cc7e8ae8SMichal Jastrzebski 		cmdline_quit(cl);
679cc7e8ae8SMichal Jastrzebski 		return;
680cc7e8ae8SMichal Jastrzebski 	}
681cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 0;
6823ca530edSPiotr Azarewicz 	if (rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore) < 0)
6833ca530edSPiotr Azarewicz 		cmdline_printf(cl,
6843ca530edSPiotr Azarewicz 				"error: lcore_main can not stop on core:%d\n",
6853ca530edSPiotr Azarewicz 				global_flag_stru_p->LcoreMainCore);
6863ca530edSPiotr Azarewicz 	else
687cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
688cc7e8ae8SMichal Jastrzebski 				"lcore_main stopped on core:%d\n",
689cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
690cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
691cc7e8ae8SMichal Jastrzebski 	cmdline_quit(cl);
692cc7e8ae8SMichal Jastrzebski }
693cc7e8ae8SMichal Jastrzebski 
694cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_quit_quit =
695cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
696cc7e8ae8SMichal Jastrzebski 
697cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_quit = {
698cc7e8ae8SMichal Jastrzebski 	.f = cmd_quit_parsed,  /* function to call */
699cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
700cc7e8ae8SMichal Jastrzebski 	.help_str = "this command do not handle any arguments",
701cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
702cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_quit_quit,
703cc7e8ae8SMichal Jastrzebski 		NULL,
704cc7e8ae8SMichal Jastrzebski 	},
705cc7e8ae8SMichal Jastrzebski };
706cc7e8ae8SMichal Jastrzebski 
707cc7e8ae8SMichal Jastrzebski struct cmd_show_result {
708cc7e8ae8SMichal Jastrzebski 	cmdline_fixed_string_t show;
709cc7e8ae8SMichal Jastrzebski };
710cc7e8ae8SMichal Jastrzebski 
711cc7e8ae8SMichal Jastrzebski static void cmd_show_parsed(__attribute__((unused)) void *parsed_result,
712cc7e8ae8SMichal Jastrzebski 			    struct cmdline *cl,
713cc7e8ae8SMichal Jastrzebski 			    __attribute__((unused)) void *data)
714cc7e8ae8SMichal Jastrzebski {
715f8244c63SZhiyong Yang 	uint16_t slaves[16] = {0};
716cc7e8ae8SMichal Jastrzebski 	uint8_t len = 16;
7176d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
718f8244c63SZhiyong Yang 	uint16_t i = 0;
719cc7e8ae8SMichal Jastrzebski 
720cc7e8ae8SMichal Jastrzebski 	while (i < slaves_count)	{
721cc7e8ae8SMichal Jastrzebski 		rte_eth_macaddr_get(i, &addr);
722cc7e8ae8SMichal Jastrzebski 		PRINT_MAC(addr);
723cc7e8ae8SMichal Jastrzebski 		printf("\n");
724cc7e8ae8SMichal Jastrzebski 		i++;
725cc7e8ae8SMichal Jastrzebski 	}
726cc7e8ae8SMichal Jastrzebski 
727cc7e8ae8SMichal Jastrzebski 	rte_spinlock_trylock(&global_flag_stru_p->lock);
728cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
729cc7e8ae8SMichal Jastrzebski 			"Active_slaves:%d "
730cc7e8ae8SMichal Jastrzebski 			"packets received:Tot:%d Arp:%d IPv4:%d\n",
731cc7e8ae8SMichal Jastrzebski 			rte_eth_bond_active_slaves_get(BOND_PORT, slaves, len),
732cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[0],
733cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[1],
734cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[2]);
735cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
736cc7e8ae8SMichal Jastrzebski }
737cc7e8ae8SMichal Jastrzebski 
738cc7e8ae8SMichal Jastrzebski cmdline_parse_token_string_t cmd_show_show =
739cc7e8ae8SMichal Jastrzebski 	TOKEN_STRING_INITIALIZER(struct cmd_show_result, show, "show");
740cc7e8ae8SMichal Jastrzebski 
741cc7e8ae8SMichal Jastrzebski cmdline_parse_inst_t cmd_show = {
742cc7e8ae8SMichal Jastrzebski 	.f = cmd_show_parsed,  /* function to call */
743cc7e8ae8SMichal Jastrzebski 	.data = NULL,      /* 2nd arg of func */
744cc7e8ae8SMichal Jastrzebski 	.help_str = "this command do not handle any arguments",
745cc7e8ae8SMichal Jastrzebski 	.tokens = {        /* token list, NULL terminated */
746cc7e8ae8SMichal Jastrzebski 		(void *)&cmd_show_show,
747cc7e8ae8SMichal Jastrzebski 		NULL,
748cc7e8ae8SMichal Jastrzebski 	},
749cc7e8ae8SMichal Jastrzebski };
750cc7e8ae8SMichal Jastrzebski 
751cc7e8ae8SMichal Jastrzebski /****** CONTEXT (list of instruction) */
752cc7e8ae8SMichal Jastrzebski 
753cc7e8ae8SMichal Jastrzebski cmdline_parse_ctx_t main_ctx[] = {
754cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_start,
755cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_obj_send,
756cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_stop,
757cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_show,
758cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_quit,
759cc7e8ae8SMichal Jastrzebski 	(cmdline_parse_inst_t *)&cmd_help,
760cc7e8ae8SMichal Jastrzebski 	NULL,
761cc7e8ae8SMichal Jastrzebski };
762cc7e8ae8SMichal Jastrzebski 
763cc7e8ae8SMichal Jastrzebski /* prompt function, called from main on MASTER lcore */
7644ae39dfaSOlivier Matz static void prompt(__attribute__((unused)) void *arg1)
765cc7e8ae8SMichal Jastrzebski {
766cc7e8ae8SMichal Jastrzebski 	struct cmdline *cl;
767cc7e8ae8SMichal Jastrzebski 
768cc7e8ae8SMichal Jastrzebski 	cl = cmdline_stdin_new(main_ctx, "bond6>");
769cc7e8ae8SMichal Jastrzebski 	if (cl != NULL) {
770cc7e8ae8SMichal Jastrzebski 		cmdline_interact(cl);
771cc7e8ae8SMichal Jastrzebski 		cmdline_stdin_exit(cl);
772cc7e8ae8SMichal Jastrzebski 	}
773cc7e8ae8SMichal Jastrzebski }
774cc7e8ae8SMichal Jastrzebski 
775cc7e8ae8SMichal Jastrzebski /* Main function, does initialisation and calls the per-lcore functions */
776cc7e8ae8SMichal Jastrzebski int
777cc7e8ae8SMichal Jastrzebski main(int argc, char *argv[])
778cc7e8ae8SMichal Jastrzebski {
7792b7a03c5SStephen Hemminger 	int ret, slave_core_id;
7808728ccf3SThomas Monjalon 	uint16_t nb_ports, i;
781cc7e8ae8SMichal Jastrzebski 
782cc7e8ae8SMichal Jastrzebski 	/* init EAL */
783cc7e8ae8SMichal Jastrzebski 	ret = rte_eal_init(argc, argv);
784b65ecf19SGaetan Rivet 	rte_devargs_dump(stdout);
785cc7e8ae8SMichal Jastrzebski 	if (ret < 0)
786cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
787cc7e8ae8SMichal Jastrzebski 	argc -= ret;
788cc7e8ae8SMichal Jastrzebski 	argv += ret;
789cc7e8ae8SMichal Jastrzebski 
790d9a42a69SThomas Monjalon 	nb_ports = rte_eth_dev_count_avail();
791cc7e8ae8SMichal Jastrzebski 	if (nb_ports == 0)
792cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Give at least one port\n");
793cc7e8ae8SMichal Jastrzebski 	else if (nb_ports > MAX_PORTS)
794cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "You can have max 4 ports\n");
795cc7e8ae8SMichal Jastrzebski 
796ea0c20eaSOlivier Matz 	mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NB_MBUF, 32,
797824cb29cSKonstantin Ananyev 		0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
798cc7e8ae8SMichal Jastrzebski 	if (mbuf_pool == NULL)
799cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
800cc7e8ae8SMichal Jastrzebski 
801cc7e8ae8SMichal Jastrzebski 	/* initialize all ports */
802cc7e8ae8SMichal Jastrzebski 	slaves_count = nb_ports;
8038728ccf3SThomas Monjalon 	RTE_ETH_FOREACH_DEV(i) {
804cc7e8ae8SMichal Jastrzebski 		slave_port_init(i, mbuf_pool);
805cc7e8ae8SMichal Jastrzebski 		slaves[i] = i;
806cc7e8ae8SMichal Jastrzebski 	}
807cc7e8ae8SMichal Jastrzebski 
808cc7e8ae8SMichal Jastrzebski 	bond_port_init(mbuf_pool);
809cc7e8ae8SMichal Jastrzebski 
810cc7e8ae8SMichal Jastrzebski 	rte_spinlock_init(&global_flag_stru_p->lock);
811cc7e8ae8SMichal Jastrzebski 
812cc7e8ae8SMichal Jastrzebski 	/* check state of lcores */
813cc7e8ae8SMichal Jastrzebski 	RTE_LCORE_FOREACH_SLAVE(slave_core_id) {
8142b7a03c5SStephen Hemminger 		if (rte_eal_get_lcore_state(slave_core_id) != WAIT)
815cc7e8ae8SMichal Jastrzebski 			return -EBUSY;
816cc7e8ae8SMichal Jastrzebski 	}
8172b7a03c5SStephen Hemminger 
818cc7e8ae8SMichal Jastrzebski 	/* start lcore main on core != master_core - ARP response thread */
819cc7e8ae8SMichal Jastrzebski 	slave_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0);
820cc7e8ae8SMichal Jastrzebski 	if ((slave_core_id >= RTE_MAX_LCORE) || (slave_core_id == 0))
821cc7e8ae8SMichal Jastrzebski 		return -EPERM;
822cc7e8ae8SMichal Jastrzebski 
823cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 1;
824cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainCore = slave_core_id;
825cc7e8ae8SMichal Jastrzebski 	printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n",
826cc7e8ae8SMichal Jastrzebski 			slave_core_id,
827cc7e8ae8SMichal Jastrzebski 			rte_eal_remote_launch((lcore_function_t *)lcore_main,
828cc7e8ae8SMichal Jastrzebski 					NULL,
829cc7e8ae8SMichal Jastrzebski 					slave_core_id),
830cc7e8ae8SMichal Jastrzebski 			BOND_IP_1,
831cc7e8ae8SMichal Jastrzebski 			BOND_IP_2,
832cc7e8ae8SMichal Jastrzebski 			BOND_IP_3,
833cc7e8ae8SMichal Jastrzebski 			BOND_IP_4
834cc7e8ae8SMichal Jastrzebski 		);
835cc7e8ae8SMichal Jastrzebski 
836cc7e8ae8SMichal Jastrzebski 	/* Start prompt for user interact */
837cc7e8ae8SMichal Jastrzebski 	prompt(NULL);
838cc7e8ae8SMichal Jastrzebski 
839cc7e8ae8SMichal Jastrzebski 	rte_delay_ms(100);
840cc7e8ae8SMichal Jastrzebski 	return 0;
841cc7e8ae8SMichal Jastrzebski }
842