xref: /dpdk/examples/bond/main.c (revision 7e06c0de1952d3109a5b0c4779d7e7d8059c9d78)
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_cycles.h>
28cc7e8ae8SMichal Jastrzebski #include <rte_prefetch.h>
29cc7e8ae8SMichal Jastrzebski #include <rte_lcore.h>
30cc7e8ae8SMichal Jastrzebski #include <rte_per_lcore.h>
31cc7e8ae8SMichal Jastrzebski #include <rte_branch_prediction.h>
32cc7e8ae8SMichal Jastrzebski #include <rte_interrupts.h>
33cc7e8ae8SMichal Jastrzebski #include <rte_random.h>
34cc7e8ae8SMichal Jastrzebski #include <rte_debug.h>
35cc7e8ae8SMichal Jastrzebski #include <rte_ether.h>
36cc7e8ae8SMichal Jastrzebski #include <rte_ethdev.h>
37cc7e8ae8SMichal Jastrzebski #include <rte_mempool.h>
38cc7e8ae8SMichal Jastrzebski #include <rte_mbuf.h>
39cc7e8ae8SMichal Jastrzebski #include <rte_ip.h>
40cc7e8ae8SMichal Jastrzebski #include <rte_tcp.h>
41cc7e8ae8SMichal Jastrzebski #include <rte_arp.h>
42cc7e8ae8SMichal Jastrzebski #include <rte_spinlock.h>
437b0de673SThomas Monjalon #include <rte_devargs.h>
447b0de673SThomas Monjalon #include <rte_byteorder.h>
457b0de673SThomas Monjalon #include <rte_cpuflags.h>
467b0de673SThomas Monjalon #include <rte_eth_bond.h>
47cc7e8ae8SMichal Jastrzebski 
48cc7e8ae8SMichal Jastrzebski #include <cmdline_socket.h>
49cfc3bc5dSBruce Richardson #include "commands.h"
50cc7e8ae8SMichal Jastrzebski 
51cc7e8ae8SMichal Jastrzebski #define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1
52cc7e8ae8SMichal Jastrzebski 
53cc7e8ae8SMichal Jastrzebski #define NB_MBUF   (1024*8)
54cc7e8ae8SMichal Jastrzebski 
55cc7e8ae8SMichal Jastrzebski #define MAX_PKT_BURST 32
56cc7e8ae8SMichal Jastrzebski #define BURST_TX_DRAIN_US 100      /* TX drain every ~100us */
57cc7e8ae8SMichal Jastrzebski #define BURST_RX_INTERVAL_NS (10) /* RX poll interval ~100ns */
58cc7e8ae8SMichal Jastrzebski 
59cc7e8ae8SMichal Jastrzebski /*
60cc7e8ae8SMichal Jastrzebski  * RX and TX Prefetch, Host, and Write-back threshold values should be
61cc7e8ae8SMichal Jastrzebski  * carefully set for optimal performance. Consult the network
62cc7e8ae8SMichal Jastrzebski  * controller's datasheet and supporting DPDK documentation for guidance
63cc7e8ae8SMichal Jastrzebski  * on how these parameters should be set.
64cc7e8ae8SMichal Jastrzebski  */
65cc7e8ae8SMichal Jastrzebski #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
66cc7e8ae8SMichal Jastrzebski #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
67cc7e8ae8SMichal Jastrzebski #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
68cc7e8ae8SMichal Jastrzebski #define RX_FTHRESH (MAX_PKT_BURST * 2)/**< Default values of RX free threshold reg. */
69cc7e8ae8SMichal Jastrzebski 
70cc7e8ae8SMichal Jastrzebski /*
71cc7e8ae8SMichal Jastrzebski  * These default values are optimized for use with the Intel(R) 82599 10 GbE
72cc7e8ae8SMichal Jastrzebski  * Controller and the DPDK ixgbe PMD. Consider using other values for other
73cc7e8ae8SMichal Jastrzebski  * network controllers and/or network drivers.
74cc7e8ae8SMichal Jastrzebski  */
75cc7e8ae8SMichal Jastrzebski #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
76cc7e8ae8SMichal Jastrzebski #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
77cc7e8ae8SMichal Jastrzebski #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
78cc7e8ae8SMichal Jastrzebski 
79cc7e8ae8SMichal Jastrzebski /*
80cc7e8ae8SMichal Jastrzebski  * Configurable number of RX/TX ring descriptors
81cc7e8ae8SMichal Jastrzebski  */
82867a6c66SKevin Laatz #define RTE_RX_DESC_DEFAULT 1024
83867a6c66SKevin Laatz #define RTE_TX_DESC_DEFAULT 1024
84cc7e8ae8SMichal Jastrzebski 
85cc7e8ae8SMichal Jastrzebski #define BOND_IP_1	7
86cc7e8ae8SMichal Jastrzebski #define BOND_IP_2	0
87cc7e8ae8SMichal Jastrzebski #define BOND_IP_3	0
88cc7e8ae8SMichal Jastrzebski #define BOND_IP_4	10
89cc7e8ae8SMichal Jastrzebski 
90cc7e8ae8SMichal Jastrzebski /* not defined under linux */
91cc7e8ae8SMichal Jastrzebski #ifndef NIPQUAD
92cc7e8ae8SMichal Jastrzebski #define NIPQUAD_FMT "%u.%u.%u.%u"
93cc7e8ae8SMichal Jastrzebski #endif
94cc7e8ae8SMichal Jastrzebski 
95cc7e8ae8SMichal Jastrzebski #define MAX_PORTS	4
96cc7e8ae8SMichal Jastrzebski #define PRINT_MAC(addr)		printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \
97cc7e8ae8SMichal Jastrzebski 		":%02"PRIx8":%02"PRIx8":%02"PRIx8,	\
98a7db3afcSAman Deep Singh 		RTE_ETHER_ADDR_BYTES(&addr))
99cc7e8ae8SMichal Jastrzebski 
10015e34522SLong Wu uint16_t members[RTE_MAX_ETHPORTS];
10115e34522SLong Wu uint16_t members_count;
102cc7e8ae8SMichal Jastrzebski 
103f8244c63SZhiyong Yang static uint16_t BOND_PORT = 0xffff;
104cc7e8ae8SMichal Jastrzebski 
105cc7e8ae8SMichal Jastrzebski static struct rte_mempool *mbuf_pool;
106cc7e8ae8SMichal Jastrzebski 
107cc7e8ae8SMichal Jastrzebski static struct rte_eth_conf port_conf = {
108cc7e8ae8SMichal Jastrzebski 	.rxmode = {
109295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_RX_NONE,
110cc7e8ae8SMichal Jastrzebski 	},
111cc7e8ae8SMichal Jastrzebski 	.rx_adv_conf = {
112cc7e8ae8SMichal Jastrzebski 		.rss_conf = {
113cc7e8ae8SMichal Jastrzebski 			.rss_key = NULL,
114295968d1SFerruh Yigit 			.rss_hf = RTE_ETH_RSS_IP,
115cc7e8ae8SMichal Jastrzebski 		},
116cc7e8ae8SMichal Jastrzebski 	},
117cc7e8ae8SMichal Jastrzebski 	.txmode = {
118295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_TX_NONE,
119cc7e8ae8SMichal Jastrzebski 	},
120cc7e8ae8SMichal Jastrzebski };
121cc7e8ae8SMichal Jastrzebski 
122cc7e8ae8SMichal Jastrzebski static void
member_port_init(uint16_t portid,struct rte_mempool * mbuf_pool)12315e34522SLong Wu member_port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
124cc7e8ae8SMichal Jastrzebski {
125cc7e8ae8SMichal Jastrzebski 	int retval;
12660efb44fSRoman Zhukov 	uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
12760efb44fSRoman Zhukov 	uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
128c1b77788SShahaf Shuler 	struct rte_eth_dev_info dev_info;
129c1b77788SShahaf Shuler 	struct rte_eth_rxconf rxq_conf;
130c1b77788SShahaf Shuler 	struct rte_eth_txconf txq_conf;
131c1b77788SShahaf Shuler 	struct rte_eth_conf local_port_conf = port_conf;
132cc7e8ae8SMichal Jastrzebski 
133a9dbe180SThomas Monjalon 	if (!rte_eth_dev_is_valid_port(portid))
134cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Invalid port\n");
135cc7e8ae8SMichal Jastrzebski 
136089e5ed7SIvan Ilchenko 	retval = rte_eth_dev_info_get(portid, &dev_info);
137089e5ed7SIvan Ilchenko 	if (retval != 0)
138089e5ed7SIvan Ilchenko 		rte_exit(EXIT_FAILURE,
139089e5ed7SIvan Ilchenko 			"Error during getting device (port %u) info: %s\n",
140089e5ed7SIvan Ilchenko 			portid, strerror(-retval));
141089e5ed7SIvan Ilchenko 
142295968d1SFerruh Yigit 	if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
143c1b77788SShahaf Shuler 		local_port_conf.txmode.offloads |=
144295968d1SFerruh Yigit 			RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
1454f5701f2SFerruh Yigit 
1464f5701f2SFerruh Yigit 	local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
1474f5701f2SFerruh Yigit 		dev_info.flow_type_rss_offloads;
1484f5701f2SFerruh Yigit 	if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
1494f5701f2SFerruh Yigit 			port_conf.rx_adv_conf.rss_conf.rss_hf) {
1504f5701f2SFerruh Yigit 		printf("Port %u modified RSS hash function based on hardware support,"
1514f5701f2SFerruh Yigit 			"requested:%#"PRIx64" configured:%#"PRIx64"\n",
1524f5701f2SFerruh Yigit 			portid,
1534f5701f2SFerruh Yigit 			port_conf.rx_adv_conf.rss_conf.rss_hf,
1544f5701f2SFerruh Yigit 			local_port_conf.rx_adv_conf.rss_conf.rss_hf);
1554f5701f2SFerruh Yigit 	}
1564f5701f2SFerruh Yigit 
157c1b77788SShahaf Shuler 	retval = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
158cc7e8ae8SMichal Jastrzebski 	if (retval != 0)
159cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n",
160cc7e8ae8SMichal Jastrzebski 				portid, retval);
161cc7e8ae8SMichal Jastrzebski 
16260efb44fSRoman Zhukov 	retval = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
16360efb44fSRoman Zhukov 	if (retval != 0)
16460efb44fSRoman Zhukov 		rte_exit(EXIT_FAILURE, "port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
16560efb44fSRoman Zhukov 				"failed (res=%d)\n", portid, retval);
16660efb44fSRoman Zhukov 
167cc7e8ae8SMichal Jastrzebski 	/* RX setup */
168c1b77788SShahaf Shuler 	rxq_conf = dev_info.default_rxconf;
169c1b77788SShahaf Shuler 	rxq_conf.offloads = local_port_conf.rxmode.offloads;
17060efb44fSRoman Zhukov 	retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
171c1b77788SShahaf Shuler 					rte_eth_dev_socket_id(portid),
172c1b77788SShahaf Shuler 					&rxq_conf,
173cc7e8ae8SMichal Jastrzebski 					mbuf_pool);
174cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
175cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)",
176cc7e8ae8SMichal Jastrzebski 				portid, retval);
177cc7e8ae8SMichal Jastrzebski 
178cc7e8ae8SMichal Jastrzebski 	/* TX setup */
179c1b77788SShahaf Shuler 	txq_conf = dev_info.default_txconf;
180c1b77788SShahaf Shuler 	txq_conf.offloads = local_port_conf.txmode.offloads;
18160efb44fSRoman Zhukov 	retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
182c1b77788SShahaf Shuler 				rte_eth_dev_socket_id(portid), &txq_conf);
183cc7e8ae8SMichal Jastrzebski 
184cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
185cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)",
186cc7e8ae8SMichal Jastrzebski 				portid, retval);
187cc7e8ae8SMichal Jastrzebski 
188cc7e8ae8SMichal Jastrzebski 	retval  = rte_eth_dev_start(portid);
189cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
190cc7e8ae8SMichal Jastrzebski 		rte_exit(retval,
191cc7e8ae8SMichal Jastrzebski 				"Start port %d failed (res=%d)",
192cc7e8ae8SMichal Jastrzebski 				portid, retval);
193cc7e8ae8SMichal Jastrzebski 
1946d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
195cc7e8ae8SMichal Jastrzebski 
19670febdcfSIgor Romanov 	retval = rte_eth_macaddr_get(portid, &addr);
19770febdcfSIgor Romanov 	if (retval != 0)
19870febdcfSIgor Romanov 		rte_exit(retval,
19970febdcfSIgor Romanov 				"Mac address get port %d failed (res=%d)",
20070febdcfSIgor Romanov 				portid, retval);
20170febdcfSIgor Romanov 
202f8244c63SZhiyong Yang 	printf("Port %u MAC: ", portid);
203cc7e8ae8SMichal Jastrzebski 	PRINT_MAC(addr);
204cc7e8ae8SMichal Jastrzebski 	printf("\n");
205cc7e8ae8SMichal Jastrzebski }
206cc7e8ae8SMichal Jastrzebski 
207cc7e8ae8SMichal Jastrzebski static void
bond_port_init(struct rte_mempool * mbuf_pool)208cc7e8ae8SMichal Jastrzebski bond_port_init(struct rte_mempool *mbuf_pool)
209cc7e8ae8SMichal Jastrzebski {
210cc7e8ae8SMichal Jastrzebski 	int retval;
211cc7e8ae8SMichal Jastrzebski 	uint8_t i;
21260efb44fSRoman Zhukov 	uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
21360efb44fSRoman Zhukov 	uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
214c1b77788SShahaf Shuler 	struct rte_eth_dev_info dev_info;
215c1b77788SShahaf Shuler 	struct rte_eth_rxconf rxq_conf;
216c1b77788SShahaf Shuler 	struct rte_eth_txconf txq_conf;
217c1b77788SShahaf Shuler 	struct rte_eth_conf local_port_conf = port_conf;
218292fdb76SRadu Nicolau 	uint16_t wait_counter = 20;
219cc7e8ae8SMichal Jastrzebski 
220e6509c6cSRadu Nicolau 	retval = rte_eth_bond_create("net_bonding0", BONDING_MODE_ALB,
221cc7e8ae8SMichal Jastrzebski 			0 /*SOCKET_ID_ANY*/);
222cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
223cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE,
2247be78d02SJosh Soref 				"Failed to create bond port\n");
225cc7e8ae8SMichal Jastrzebski 
226f8244c63SZhiyong Yang 	BOND_PORT = retval;
227cc7e8ae8SMichal Jastrzebski 
228089e5ed7SIvan Ilchenko 	retval = rte_eth_dev_info_get(BOND_PORT, &dev_info);
229089e5ed7SIvan Ilchenko 	if (retval != 0)
230089e5ed7SIvan Ilchenko 		rte_exit(EXIT_FAILURE,
231089e5ed7SIvan Ilchenko 			"Error during getting device (port %u) info: %s\n",
232089e5ed7SIvan Ilchenko 			BOND_PORT, strerror(-retval));
233089e5ed7SIvan Ilchenko 
234295968d1SFerruh Yigit 	if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
235c1b77788SShahaf Shuler 		local_port_conf.txmode.offloads |=
236295968d1SFerruh Yigit 			RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
237c1b77788SShahaf Shuler 	retval = rte_eth_dev_configure(BOND_PORT, 1, 1, &local_port_conf);
238cc7e8ae8SMichal Jastrzebski 	if (retval != 0)
239cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n",
240cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
241cc7e8ae8SMichal Jastrzebski 
24260efb44fSRoman Zhukov 	retval = rte_eth_dev_adjust_nb_rx_tx_desc(BOND_PORT, &nb_rxd, &nb_txd);
24360efb44fSRoman Zhukov 	if (retval != 0)
24460efb44fSRoman Zhukov 		rte_exit(EXIT_FAILURE, "port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
24560efb44fSRoman Zhukov 				"failed (res=%d)\n", BOND_PORT, retval);
24660efb44fSRoman Zhukov 
24715e34522SLong Wu 	for (i = 0; i < members_count; i++) {
24815e34522SLong Wu 		if (rte_eth_bond_member_add(BOND_PORT, members[i]) == -1)
24915e34522SLong Wu 			rte_exit(-1, "Oooops! adding member (%u) to bond (%u) failed!\n",
25015e34522SLong Wu 					members[i], BOND_PORT);
2512eee509cSRadu Nicolau 
2522eee509cSRadu Nicolau 	}
2532eee509cSRadu Nicolau 
254cc7e8ae8SMichal Jastrzebski 	/* RX setup */
255c1b77788SShahaf Shuler 	rxq_conf = dev_info.default_rxconf;
256c1b77788SShahaf Shuler 	rxq_conf.offloads = local_port_conf.rxmode.offloads;
25760efb44fSRoman Zhukov 	retval = rte_eth_rx_queue_setup(BOND_PORT, 0, nb_rxd,
258c1b77788SShahaf Shuler 					rte_eth_dev_socket_id(BOND_PORT),
259c1b77788SShahaf Shuler 					&rxq_conf, mbuf_pool);
260cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
261cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)",
262cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
263cc7e8ae8SMichal Jastrzebski 
264cc7e8ae8SMichal Jastrzebski 	/* TX setup */
265c1b77788SShahaf Shuler 	txq_conf = dev_info.default_txconf;
266c1b77788SShahaf Shuler 	txq_conf.offloads = local_port_conf.txmode.offloads;
26760efb44fSRoman Zhukov 	retval = rte_eth_tx_queue_setup(BOND_PORT, 0, nb_txd,
268c1b77788SShahaf Shuler 				rte_eth_dev_socket_id(BOND_PORT), &txq_conf);
269cc7e8ae8SMichal Jastrzebski 
270cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
271cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)",
272cc7e8ae8SMichal Jastrzebski 				BOND_PORT, retval);
273cc7e8ae8SMichal Jastrzebski 
274cc7e8ae8SMichal Jastrzebski 	retval  = rte_eth_dev_start(BOND_PORT);
275cc7e8ae8SMichal Jastrzebski 	if (retval < 0)
276cc7e8ae8SMichal Jastrzebski 		rte_exit(retval, "Start port %d failed (res=%d)", BOND_PORT, retval);
277cc7e8ae8SMichal Jastrzebski 
27815e34522SLong Wu 	printf("Waiting for members to become active...");
279292fdb76SRadu Nicolau 	while (wait_counter) {
28015e34522SLong Wu 		uint16_t act_members[16] = {0};
28115e34522SLong Wu 		if (rte_eth_bond_active_members_get(BOND_PORT, act_members, 16) ==
28215e34522SLong Wu 				members_count) {
283292fdb76SRadu Nicolau 			printf("\n");
284292fdb76SRadu Nicolau 			break;
285292fdb76SRadu Nicolau 		}
286292fdb76SRadu Nicolau 		sleep(1);
287292fdb76SRadu Nicolau 		printf("...");
288292fdb76SRadu Nicolau 		if (--wait_counter == 0)
28915e34522SLong Wu 			rte_exit(-1, "\nFailed to activate members\n");
290292fdb76SRadu Nicolau 	}
291292fdb76SRadu Nicolau 
292f430bbceSIvan Ilchenko 	retval = rte_eth_promiscuous_enable(BOND_PORT);
293f430bbceSIvan Ilchenko 	if (retval != 0) {
294f430bbceSIvan Ilchenko 		rte_exit(EXIT_FAILURE,
295f430bbceSIvan Ilchenko 				"port %u: promiscuous mode enable failed: %s\n",
296f430bbceSIvan Ilchenko 				BOND_PORT, rte_strerror(-retval));
297f430bbceSIvan Ilchenko 		return;
298f430bbceSIvan Ilchenko 	}
299cc7e8ae8SMichal Jastrzebski 
3006d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
301cc7e8ae8SMichal Jastrzebski 
30270febdcfSIgor Romanov 	retval = rte_eth_macaddr_get(BOND_PORT, &addr);
30370febdcfSIgor Romanov 	if (retval != 0)
30470febdcfSIgor Romanov 		rte_exit(retval, "port %u: Mac address get failed (res=%d)",
30570febdcfSIgor Romanov 				BOND_PORT, retval);
30670febdcfSIgor Romanov 
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
get_vlan_offset(struct rte_ether_hdr * eth_hdr,uint16_t * proto)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  */
lcore_main(__rte_unused void * arg1)347f2fc83b4SThomas Monjalon static int lcore_main(__rte_unused void *arg1)
348cc7e8ae8SMichal Jastrzebski {
349*7e06c0deSTyler Retzlaff 	alignas(RTE_CACHE_LINE_SIZE) struct rte_mbuf *pkts[MAX_PKT_BURST];
35004d43857SDmitry Kozlyuk 	struct rte_ether_addr dst_addr;
351cc7e8ae8SMichal Jastrzebski 
35270febdcfSIgor Romanov 	struct rte_ether_addr bond_mac_addr;
3536d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
354f2745bfeSOlivier Matz 	struct rte_arp_hdr *arp_hdr;
355a7c528e5SOlivier Matz 	struct rte_ipv4_hdr *ipv4_hdr;
356cc7e8ae8SMichal Jastrzebski 	uint16_t ether_type, offset;
357cc7e8ae8SMichal Jastrzebski 
358cc7e8ae8SMichal Jastrzebski 	uint16_t rx_cnt;
359cc7e8ae8SMichal Jastrzebski 	uint32_t bond_ip;
360cc7e8ae8SMichal Jastrzebski 	int i = 0;
361cc7e8ae8SMichal Jastrzebski 	uint8_t is_free;
36270febdcfSIgor Romanov 	int ret;
363cc7e8ae8SMichal Jastrzebski 
364cc7e8ae8SMichal Jastrzebski 	bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
365cc7e8ae8SMichal Jastrzebski 				(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
366cc7e8ae8SMichal Jastrzebski 
36703382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
368cc7e8ae8SMichal Jastrzebski 
369cc7e8ae8SMichal Jastrzebski 	while (global_flag_stru_p->LcoreMainIsRunning) {
370cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
371cc7e8ae8SMichal Jastrzebski 		rx_cnt = rte_eth_rx_burst(BOND_PORT, 0, pkts, MAX_PKT_BURST);
372cc7e8ae8SMichal Jastrzebski 		is_free = 0;
373cc7e8ae8SMichal Jastrzebski 
374cc7e8ae8SMichal Jastrzebski 		/* If didn't receive any packets, wait and go to next iteration */
375cc7e8ae8SMichal Jastrzebski 		if (rx_cnt == 0) {
376cc7e8ae8SMichal Jastrzebski 			rte_delay_us(50);
377cc7e8ae8SMichal Jastrzebski 			continue;
378cc7e8ae8SMichal Jastrzebski 		}
379cc7e8ae8SMichal Jastrzebski 
38070febdcfSIgor Romanov 		ret = rte_eth_macaddr_get(BOND_PORT, &bond_mac_addr);
38170febdcfSIgor Romanov 		if (ret != 0) {
38270febdcfSIgor Romanov 			printf("Bond (port %u) MAC address get failed: %s.\n"
38370febdcfSIgor Romanov 			       "%u packets dropped", BOND_PORT, strerror(-ret),
38470febdcfSIgor Romanov 			       rx_cnt);
38570febdcfSIgor Romanov 			rte_pktmbuf_free(pkts[i]);
38670febdcfSIgor Romanov 			continue;
38770febdcfSIgor Romanov 		}
38870febdcfSIgor Romanov 
389cc7e8ae8SMichal Jastrzebski 		/* Search incoming data for ARP packets and prepare response */
390cc7e8ae8SMichal Jastrzebski 		for (i = 0; i < rx_cnt; i++) {
391cc7e8ae8SMichal Jastrzebski 			if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1) {
392cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->port_packets[0]++;
393cc7e8ae8SMichal Jastrzebski 				rte_spinlock_unlock(&global_flag_stru_p->lock);
394cc7e8ae8SMichal Jastrzebski 			}
3956d13ea8eSOlivier Matz 			eth_hdr = rte_pktmbuf_mtod(pkts[i],
3966d13ea8eSOlivier Matz 						struct rte_ether_hdr *);
397cc7e8ae8SMichal Jastrzebski 			ether_type = eth_hdr->ether_type;
39835b2d13fSOlivier Matz 			if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN))
3997be78d02SJosh Soref 				printf("VLAN tagged frame, offset:");
400cc7e8ae8SMichal Jastrzebski 			offset = get_vlan_offset(eth_hdr, &ether_type);
401cc7e8ae8SMichal Jastrzebski 			if (offset > 0)
402cc7e8ae8SMichal Jastrzebski 				printf("%d\n", offset);
40335b2d13fSOlivier Matz 			if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
404cc7e8ae8SMichal Jastrzebski 				if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1)     {
405cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->port_packets[1]++;
406cc7e8ae8SMichal Jastrzebski 					rte_spinlock_unlock(&global_flag_stru_p->lock);
407cc7e8ae8SMichal Jastrzebski 				}
408f2745bfeSOlivier Matz 				arp_hdr = (struct rte_arp_hdr *)(
409f2745bfeSOlivier Matz 					(char *)(eth_hdr + 1) + offset);
410cc7e8ae8SMichal Jastrzebski 				if (arp_hdr->arp_data.arp_tip == bond_ip) {
411e482e0faSOlivier Matz 					if (arp_hdr->arp_opcode == rte_cpu_to_be_16(RTE_ARP_OP_REQUEST)) {
412e482e0faSOlivier Matz 						arp_hdr->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
413cc7e8ae8SMichal Jastrzebski 						/* Switch src and dst data and set bonding MAC */
41404d43857SDmitry Kozlyuk 						rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
41504d43857SDmitry Kozlyuk 						rte_ether_addr_copy(&bond_mac_addr, &eth_hdr->src_addr);
416538da7a1SOlivier Matz 						rte_ether_addr_copy(&arp_hdr->arp_data.arp_sha,
417538da7a1SOlivier Matz 								&arp_hdr->arp_data.arp_tha);
418cc7e8ae8SMichal Jastrzebski 						arp_hdr->arp_data.arp_tip = arp_hdr->arp_data.arp_sip;
41904d43857SDmitry Kozlyuk 						rte_ether_addr_copy(&bond_mac_addr, &dst_addr);
42004d43857SDmitry Kozlyuk 						rte_ether_addr_copy(&dst_addr, &arp_hdr->arp_data.arp_sha);
421cc7e8ae8SMichal Jastrzebski 						arp_hdr->arp_data.arp_sip = bond_ip;
422cc7e8ae8SMichal Jastrzebski 						rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1);
423cc7e8ae8SMichal Jastrzebski 						is_free = 1;
424cc7e8ae8SMichal Jastrzebski 					} else {
425cc7e8ae8SMichal Jastrzebski 						rte_eth_tx_burst(BOND_PORT, 0, NULL, 0);
426cc7e8ae8SMichal Jastrzebski 					}
427cc7e8ae8SMichal Jastrzebski 				}
4280c9da755SDavid Marchand 			} else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
429cc7e8ae8SMichal Jastrzebski 				if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1)     {
430cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->port_packets[2]++;
431cc7e8ae8SMichal Jastrzebski 					rte_spinlock_unlock(&global_flag_stru_p->lock);
432cc7e8ae8SMichal Jastrzebski 				 }
433a7c528e5SOlivier Matz 				ipv4_hdr = (struct rte_ipv4_hdr *)((char *)(eth_hdr + 1) + offset);
434cc7e8ae8SMichal Jastrzebski 				if (ipv4_hdr->dst_addr == bond_ip) {
43504d43857SDmitry Kozlyuk 					rte_ether_addr_copy(&eth_hdr->src_addr,
43604d43857SDmitry Kozlyuk 							&eth_hdr->dst_addr);
43704d43857SDmitry Kozlyuk 					rte_ether_addr_copy(&bond_mac_addr,
43804d43857SDmitry Kozlyuk 							&eth_hdr->src_addr);
439cc7e8ae8SMichal Jastrzebski 					ipv4_hdr->dst_addr = ipv4_hdr->src_addr;
440cc7e8ae8SMichal Jastrzebski 					ipv4_hdr->src_addr = bond_ip;
441cc7e8ae8SMichal Jastrzebski 					rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1);
442cc7e8ae8SMichal Jastrzebski 				}
443cc7e8ae8SMichal Jastrzebski 
444cc7e8ae8SMichal Jastrzebski 			}
445cc7e8ae8SMichal Jastrzebski 
446cc7e8ae8SMichal Jastrzebski 			/* Free processed packets */
447cc7e8ae8SMichal Jastrzebski 			if (is_free == 0)
448cc7e8ae8SMichal Jastrzebski 				rte_pktmbuf_free(pkts[i]);
449cc7e8ae8SMichal Jastrzebski 		}
45003382cf4SMattias Rönnblom 		rte_spinlock_lock(&global_flag_stru_p->lock);
451cc7e8ae8SMichal Jastrzebski 	}
452cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
453cc7e8ae8SMichal Jastrzebski 	printf("BYE lcore_main\n");
454cc7e8ae8SMichal Jastrzebski 	return 0;
455cc7e8ae8SMichal Jastrzebski }
456cc7e8ae8SMichal Jastrzebski 
get_string(struct cmd_send_result * res,char * buf,uint8_t size)457cfc3bc5dSBruce Richardson static inline void get_string(struct cmd_send_result *res, char *buf, uint8_t size)
458cc7e8ae8SMichal Jastrzebski {
459cc7e8ae8SMichal Jastrzebski 	snprintf(buf, size, NIPQUAD_FMT,
460cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[0]),
461cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[1]),
462cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[2]),
463cc7e8ae8SMichal Jastrzebski 		((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[3])
464cc7e8ae8SMichal Jastrzebski 		);
465cc7e8ae8SMichal Jastrzebski }
466cfc3bc5dSBruce Richardson void
cmd_send_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)467cfc3bc5dSBruce Richardson cmd_send_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data)
468cc7e8ae8SMichal Jastrzebski {
469cc7e8ae8SMichal Jastrzebski 
470cfc3bc5dSBruce Richardson 	struct cmd_send_result *res = parsed_result;
471cc7e8ae8SMichal Jastrzebski 	char ip_str[INET6_ADDRSTRLEN];
472cc7e8ae8SMichal Jastrzebski 
47370febdcfSIgor Romanov 	struct rte_ether_addr bond_mac_addr;
474cc7e8ae8SMichal Jastrzebski 	struct rte_mbuf *created_pkt;
4756d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
476f2745bfeSOlivier Matz 	struct rte_arp_hdr *arp_hdr;
477cc7e8ae8SMichal Jastrzebski 
478cc7e8ae8SMichal Jastrzebski 	uint32_t bond_ip;
479cc7e8ae8SMichal Jastrzebski 	size_t pkt_size;
48070febdcfSIgor Romanov 	int ret;
481cc7e8ae8SMichal Jastrzebski 
482cc7e8ae8SMichal Jastrzebski 	if (res->ip.family == AF_INET)
483cc7e8ae8SMichal Jastrzebski 		get_string(res, ip_str, INET_ADDRSTRLEN);
484cc7e8ae8SMichal Jastrzebski 	else
485cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl, "Wrong IP format. Only IPv4 is supported\n");
486cc7e8ae8SMichal Jastrzebski 
487cc7e8ae8SMichal Jastrzebski 	bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
488cc7e8ae8SMichal Jastrzebski 				(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
489cc7e8ae8SMichal Jastrzebski 
49070febdcfSIgor Romanov 	ret = rte_eth_macaddr_get(BOND_PORT, &bond_mac_addr);
49170febdcfSIgor Romanov 	if (ret != 0) {
49270febdcfSIgor Romanov 		cmdline_printf(cl,
49370febdcfSIgor Romanov 			       "Failed to get bond (port %u) MAC address: %s\n",
49470febdcfSIgor Romanov 			       BOND_PORT, strerror(-ret));
49570febdcfSIgor Romanov 	}
49670febdcfSIgor Romanov 
497cc7e8ae8SMichal Jastrzebski 	created_pkt = rte_pktmbuf_alloc(mbuf_pool);
4980bb76fc9SRadu Nicolau 	if (created_pkt == NULL) {
4990bb76fc9SRadu Nicolau 		cmdline_printf(cl, "Failed to allocate mbuf\n");
5000bb76fc9SRadu Nicolau 		return;
5010bb76fc9SRadu Nicolau 	}
5020bb76fc9SRadu Nicolau 
5036d13ea8eSOlivier Matz 	pkt_size = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);
504cc7e8ae8SMichal Jastrzebski 	created_pkt->data_len = pkt_size;
505cc7e8ae8SMichal Jastrzebski 	created_pkt->pkt_len = pkt_size;
506cc7e8ae8SMichal Jastrzebski 
5076d13ea8eSOlivier Matz 	eth_hdr = rte_pktmbuf_mtod(created_pkt, struct rte_ether_hdr *);
50804d43857SDmitry Kozlyuk 	rte_ether_addr_copy(&bond_mac_addr, &eth_hdr->src_addr);
50904d43857SDmitry Kozlyuk 	memset(&eth_hdr->dst_addr, 0xFF, RTE_ETHER_ADDR_LEN);
51035b2d13fSOlivier Matz 	eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
511cc7e8ae8SMichal Jastrzebski 
512f2745bfeSOlivier Matz 	arp_hdr = (struct rte_arp_hdr *)(
5136d13ea8eSOlivier Matz 		(char *)eth_hdr + sizeof(struct rte_ether_hdr));
514e482e0faSOlivier Matz 	arp_hdr->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
5150c9da755SDavid Marchand 	arp_hdr->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
51635b2d13fSOlivier Matz 	arp_hdr->arp_hlen = RTE_ETHER_ADDR_LEN;
517f2745bfeSOlivier Matz 	arp_hdr->arp_plen = sizeof(uint32_t);
518e482e0faSOlivier Matz 	arp_hdr->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REQUEST);
519cc7e8ae8SMichal Jastrzebski 
52070febdcfSIgor Romanov 	rte_ether_addr_copy(&bond_mac_addr, &arp_hdr->arp_data.arp_sha);
521cc7e8ae8SMichal Jastrzebski 	arp_hdr->arp_data.arp_sip = bond_ip;
52235b2d13fSOlivier Matz 	memset(&arp_hdr->arp_data.arp_tha, 0, RTE_ETHER_ADDR_LEN);
523cc7e8ae8SMichal Jastrzebski 	arp_hdr->arp_data.arp_tip =
524cc7e8ae8SMichal Jastrzebski 			  ((unsigned char *)&res->ip.addr.ipv4)[0]        |
525cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[1] << 8)  |
526cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[2] << 16) |
527cc7e8ae8SMichal Jastrzebski 			 (((unsigned char *)&res->ip.addr.ipv4)[3] << 24);
528cc7e8ae8SMichal Jastrzebski 	rte_eth_tx_burst(BOND_PORT, 0, &created_pkt, 1);
529cc7e8ae8SMichal Jastrzebski 
530cc7e8ae8SMichal Jastrzebski 	rte_delay_ms(100);
531cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl, "\n");
532cc7e8ae8SMichal Jastrzebski }
533cc7e8ae8SMichal Jastrzebski 
534cfc3bc5dSBruce Richardson void
cmd_start_parsed(__rte_unused void * parsed_result,struct cmdline * cl,__rte_unused void * data)535cfc3bc5dSBruce Richardson cmd_start_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data)
536cc7e8ae8SMichal Jastrzebski {
537cb056611SStephen Hemminger 	int worker_core_id = rte_lcore_id();
538cc7e8ae8SMichal Jastrzebski 
53903382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
540cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0) {
5412b7a03c5SStephen Hemminger 		if (rte_eal_get_lcore_state(global_flag_stru_p->LcoreMainCore)
5422b7a03c5SStephen Hemminger 		    != WAIT) {
543cc7e8ae8SMichal Jastrzebski 			rte_spinlock_unlock(&global_flag_stru_p->lock);
544cc7e8ae8SMichal Jastrzebski 			return;
545cc7e8ae8SMichal Jastrzebski 		}
546cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
547cc7e8ae8SMichal Jastrzebski 	} else {
548cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl, "lcore_main already running on core:%d\n",
549cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
550cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
551cc7e8ae8SMichal Jastrzebski 		return;
552cc7e8ae8SMichal Jastrzebski 	}
553cc7e8ae8SMichal Jastrzebski 
554cb056611SStephen Hemminger 	/* start lcore main on core != main_core - ARP response thread */
555cb056611SStephen Hemminger 	worker_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0);
556cb056611SStephen Hemminger 	if ((worker_core_id >= RTE_MAX_LCORE) || (worker_core_id == 0))
557cc7e8ae8SMichal Jastrzebski 		return;
558cc7e8ae8SMichal Jastrzebski 
55903382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
560cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 1;
561cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
562cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
563cc7e8ae8SMichal Jastrzebski 			"Starting lcore_main on core %d:%d "
564cc7e8ae8SMichal Jastrzebski 			"Our IP:%d.%d.%d.%d\n",
565cb056611SStephen Hemminger 			worker_core_id,
566cb056611SStephen Hemminger 			rte_eal_remote_launch(lcore_main, NULL, worker_core_id),
567cc7e8ae8SMichal Jastrzebski 			BOND_IP_1,
568cc7e8ae8SMichal Jastrzebski 			BOND_IP_2,
569cc7e8ae8SMichal Jastrzebski 			BOND_IP_3,
570cc7e8ae8SMichal Jastrzebski 			BOND_IP_4
571cc7e8ae8SMichal Jastrzebski 		);
572cc7e8ae8SMichal Jastrzebski }
573cc7e8ae8SMichal Jastrzebski 
574cfc3bc5dSBruce Richardson void
cmd_help_parsed(__rte_unused void * parsed_result,struct cmdline * cl,__rte_unused void * data)575cfc3bc5dSBruce Richardson cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data)
576cc7e8ae8SMichal Jastrzebski {
577cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
578cc7e8ae8SMichal Jastrzebski 			"ALB - link bonding mode 6 example\n"
57998a7ea33SJerin Jacob 			"send IP	- sends one ARPrequest through bonding for IP.\n"
580cc7e8ae8SMichal Jastrzebski 			"start		- starts listening ARPs.\n"
581cc7e8ae8SMichal Jastrzebski 			"stop		- stops lcore_main.\n"
58215e34522SLong Wu 			"show		- shows some bond info: ex. active members etc.\n"
583cc7e8ae8SMichal Jastrzebski 			"help		- prints help.\n"
584cc7e8ae8SMichal Jastrzebski 			"quit		- terminate all threads and quit.\n"
585cc7e8ae8SMichal Jastrzebski 		       );
586cc7e8ae8SMichal Jastrzebski }
587cc7e8ae8SMichal Jastrzebski 
588cfc3bc5dSBruce Richardson void
cmd_stop_parsed(__rte_unused void * parsed_result,struct cmdline * cl,__rte_unused void * data)589cfc3bc5dSBruce Richardson cmd_stop_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data)
590cc7e8ae8SMichal Jastrzebski {
59103382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
592cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0)	{
593cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
594cc7e8ae8SMichal Jastrzebski 					"lcore_main not running on core:%d\n",
595cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->LcoreMainCore);
596cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
597cc7e8ae8SMichal Jastrzebski 		return;
598cc7e8ae8SMichal Jastrzebski 	}
599cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 0;
6003ca530edSPiotr Azarewicz 	if (rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore) < 0)
6013ca530edSPiotr Azarewicz 		cmdline_printf(cl,
6023ca530edSPiotr Azarewicz 				"error: lcore_main can not stop on core:%d\n",
6033ca530edSPiotr Azarewicz 				global_flag_stru_p->LcoreMainCore);
6043ca530edSPiotr Azarewicz 	else
605cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
606cc7e8ae8SMichal Jastrzebski 				"lcore_main stopped on core:%d\n",
607cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
608cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
609cc7e8ae8SMichal Jastrzebski }
610cc7e8ae8SMichal Jastrzebski 
611cfc3bc5dSBruce Richardson void
cmd_quit_parsed(__rte_unused void * parsed_result,struct cmdline * cl,__rte_unused void * data)612cfc3bc5dSBruce Richardson cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data)
613cc7e8ae8SMichal Jastrzebski {
61403382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
615cc7e8ae8SMichal Jastrzebski 	if (global_flag_stru_p->LcoreMainIsRunning == 0)	{
616cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
617cc7e8ae8SMichal Jastrzebski 					"lcore_main not running on core:%d\n",
618cc7e8ae8SMichal Jastrzebski 					global_flag_stru_p->LcoreMainCore);
619cc7e8ae8SMichal Jastrzebski 		rte_spinlock_unlock(&global_flag_stru_p->lock);
620cc7e8ae8SMichal Jastrzebski 		cmdline_quit(cl);
621cc7e8ae8SMichal Jastrzebski 		return;
622cc7e8ae8SMichal Jastrzebski 	}
623cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 0;
6243ca530edSPiotr Azarewicz 	if (rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore) < 0)
6253ca530edSPiotr Azarewicz 		cmdline_printf(cl,
6263ca530edSPiotr Azarewicz 				"error: lcore_main can not stop on core:%d\n",
6273ca530edSPiotr Azarewicz 				global_flag_stru_p->LcoreMainCore);
6283ca530edSPiotr Azarewicz 	else
629cc7e8ae8SMichal Jastrzebski 		cmdline_printf(cl,
630cc7e8ae8SMichal Jastrzebski 				"lcore_main stopped on core:%d\n",
631cc7e8ae8SMichal Jastrzebski 				global_flag_stru_p->LcoreMainCore);
632cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
633cc7e8ae8SMichal Jastrzebski 	cmdline_quit(cl);
634cc7e8ae8SMichal Jastrzebski }
635cc7e8ae8SMichal Jastrzebski 
636cfc3bc5dSBruce Richardson void
cmd_show_parsed(__rte_unused void * parsed_result,struct cmdline * cl,__rte_unused void * data)637cfc3bc5dSBruce Richardson cmd_show_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data)
638cc7e8ae8SMichal Jastrzebski {
63915e34522SLong Wu 	uint16_t members[16] = {0};
640cc7e8ae8SMichal Jastrzebski 	uint8_t len = 16;
6416d13ea8eSOlivier Matz 	struct rte_ether_addr addr;
64270febdcfSIgor Romanov 	uint16_t i;
64370febdcfSIgor Romanov 	int ret;
644cc7e8ae8SMichal Jastrzebski 
64515e34522SLong Wu 	for (i = 0; i < members_count; i++) {
64670febdcfSIgor Romanov 		ret = rte_eth_macaddr_get(i, &addr);
64770febdcfSIgor Romanov 		if (ret != 0) {
64870febdcfSIgor Romanov 			cmdline_printf(cl,
64970febdcfSIgor Romanov 				"Failed to get port %u MAC address: %s\n",
65070febdcfSIgor Romanov 				i, strerror(-ret));
65170febdcfSIgor Romanov 			continue;
65270febdcfSIgor Romanov 		}
65370febdcfSIgor Romanov 
654cc7e8ae8SMichal Jastrzebski 		PRINT_MAC(addr);
655cc7e8ae8SMichal Jastrzebski 		printf("\n");
656cc7e8ae8SMichal Jastrzebski 	}
657cc7e8ae8SMichal Jastrzebski 
65803382cf4SMattias Rönnblom 	rte_spinlock_lock(&global_flag_stru_p->lock);
659cc7e8ae8SMichal Jastrzebski 	cmdline_printf(cl,
66015e34522SLong Wu 			"Active_members:%d "
661cc7e8ae8SMichal Jastrzebski 			"packets received:Tot:%d Arp:%d IPv4:%d\n",
66215e34522SLong Wu 			rte_eth_bond_active_members_get(BOND_PORT, members, len),
663cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[0],
664cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[1],
665cc7e8ae8SMichal Jastrzebski 			global_flag_stru_p->port_packets[2]);
666cc7e8ae8SMichal Jastrzebski 	rte_spinlock_unlock(&global_flag_stru_p->lock);
667cc7e8ae8SMichal Jastrzebski }
668cc7e8ae8SMichal Jastrzebski 
669cb056611SStephen Hemminger /* prompt function, called from main on MAIN lcore */
prompt(__rte_unused void * arg1)670f2fc83b4SThomas Monjalon static void prompt(__rte_unused void *arg1)
671cc7e8ae8SMichal Jastrzebski {
672cc7e8ae8SMichal Jastrzebski 	struct cmdline *cl;
673cc7e8ae8SMichal Jastrzebski 
674cc7e8ae8SMichal Jastrzebski 	cl = cmdline_stdin_new(main_ctx, "bond6>");
675cc7e8ae8SMichal Jastrzebski 	if (cl != NULL) {
676cc7e8ae8SMichal Jastrzebski 		cmdline_interact(cl);
677cc7e8ae8SMichal Jastrzebski 		cmdline_stdin_exit(cl);
678cc7e8ae8SMichal Jastrzebski 	}
679cc7e8ae8SMichal Jastrzebski }
680cc7e8ae8SMichal Jastrzebski 
681cc7e8ae8SMichal Jastrzebski /* Main function, does initialisation and calls the per-lcore functions */
682cc7e8ae8SMichal Jastrzebski int
main(int argc,char * argv[])683cc7e8ae8SMichal Jastrzebski main(int argc, char *argv[])
684cc7e8ae8SMichal Jastrzebski {
685cb056611SStephen Hemminger 	int ret, worker_core_id;
6868728ccf3SThomas Monjalon 	uint16_t nb_ports, i;
687cc7e8ae8SMichal Jastrzebski 
688cc7e8ae8SMichal Jastrzebski 	/* init EAL */
689cc7e8ae8SMichal Jastrzebski 	ret = rte_eal_init(argc, argv);
690b65ecf19SGaetan Rivet 	rte_devargs_dump(stdout);
691cc7e8ae8SMichal Jastrzebski 	if (ret < 0)
692cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
693cc7e8ae8SMichal Jastrzebski 	argc -= ret;
694cc7e8ae8SMichal Jastrzebski 	argv += ret;
695cc7e8ae8SMichal Jastrzebski 
696d9a42a69SThomas Monjalon 	nb_ports = rte_eth_dev_count_avail();
697cc7e8ae8SMichal Jastrzebski 	if (nb_ports == 0)
698cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Give at least one port\n");
699cc7e8ae8SMichal Jastrzebski 	else if (nb_ports > MAX_PORTS)
700cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "You can have max 4 ports\n");
701cc7e8ae8SMichal Jastrzebski 
702ea0c20eaSOlivier Matz 	mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NB_MBUF, 32,
703824cb29cSKonstantin Ananyev 		0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
704cc7e8ae8SMichal Jastrzebski 	if (mbuf_pool == NULL)
705cc7e8ae8SMichal Jastrzebski 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
706cc7e8ae8SMichal Jastrzebski 
707cc7e8ae8SMichal Jastrzebski 	/* initialize all ports */
70815e34522SLong Wu 	members_count = nb_ports;
7098728ccf3SThomas Monjalon 	RTE_ETH_FOREACH_DEV(i) {
71015e34522SLong Wu 		member_port_init(i, mbuf_pool);
71115e34522SLong Wu 		members[i] = i;
712cc7e8ae8SMichal Jastrzebski 	}
713cc7e8ae8SMichal Jastrzebski 
714cc7e8ae8SMichal Jastrzebski 	bond_port_init(mbuf_pool);
715cc7e8ae8SMichal Jastrzebski 
716cc7e8ae8SMichal Jastrzebski 	rte_spinlock_init(&global_flag_stru_p->lock);
717cc7e8ae8SMichal Jastrzebski 
718cc7e8ae8SMichal Jastrzebski 	/* check state of lcores */
719cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(worker_core_id) {
720cb056611SStephen Hemminger 		if (rte_eal_get_lcore_state(worker_core_id) != WAIT)
721cc7e8ae8SMichal Jastrzebski 			return -EBUSY;
722cc7e8ae8SMichal Jastrzebski 	}
7232b7a03c5SStephen Hemminger 
724cb056611SStephen Hemminger 	/* start lcore main on core != main_core - ARP response thread */
725cb056611SStephen Hemminger 	worker_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0);
726cb056611SStephen Hemminger 	if ((worker_core_id >= RTE_MAX_LCORE) || (worker_core_id == 0))
727cc7e8ae8SMichal Jastrzebski 		return -EPERM;
728cc7e8ae8SMichal Jastrzebski 
729cc7e8ae8SMichal Jastrzebski 	global_flag_stru_p->LcoreMainIsRunning = 1;
730cb056611SStephen Hemminger 	global_flag_stru_p->LcoreMainCore = worker_core_id;
731cc7e8ae8SMichal Jastrzebski 	printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n",
732cb056611SStephen Hemminger 			worker_core_id,
733cc7e8ae8SMichal Jastrzebski 			rte_eal_remote_launch((lcore_function_t *)lcore_main,
734cc7e8ae8SMichal Jastrzebski 					NULL,
735cb056611SStephen Hemminger 					worker_core_id),
736cc7e8ae8SMichal Jastrzebski 			BOND_IP_1,
737cc7e8ae8SMichal Jastrzebski 			BOND_IP_2,
738cc7e8ae8SMichal Jastrzebski 			BOND_IP_3,
739cc7e8ae8SMichal Jastrzebski 			BOND_IP_4
740cc7e8ae8SMichal Jastrzebski 		);
741cc7e8ae8SMichal Jastrzebski 
742cc7e8ae8SMichal Jastrzebski 	/* Start prompt for user interact */
743cc7e8ae8SMichal Jastrzebski 	prompt(NULL);
744cc7e8ae8SMichal Jastrzebski 
745cc7e8ae8SMichal Jastrzebski 	rte_delay_ms(100);
74610aa3757SChengchang Tang 
74710aa3757SChengchang Tang 	/* clean up the EAL */
74810aa3757SChengchang Tang 	rte_eal_cleanup();
74910aa3757SChengchang Tang 
750cc7e8ae8SMichal Jastrzebski 	return 0;
751cc7e8ae8SMichal Jastrzebski }
752