xref: /dpdk/examples/skeleton/basicfwd.c (revision 98a1648109b8dbaa4e6b821c17d1f6bd86d33a9a)
17107e471SBruce Richardson /*-
27107e471SBruce Richardson  *   BSD LICENSE
37107e471SBruce Richardson  *
47107e471SBruce Richardson  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
57107e471SBruce Richardson  *   All rights reserved.
67107e471SBruce Richardson  *
77107e471SBruce Richardson  *   Redistribution and use in source and binary forms, with or without
87107e471SBruce Richardson  *   modification, are permitted provided that the following conditions
97107e471SBruce Richardson  *   are met:
107107e471SBruce Richardson  *
117107e471SBruce Richardson  *     * Redistributions of source code must retain the above copyright
127107e471SBruce Richardson  *       notice, this list of conditions and the following disclaimer.
137107e471SBruce Richardson  *     * Redistributions in binary form must reproduce the above copyright
147107e471SBruce Richardson  *       notice, this list of conditions and the following disclaimer in
157107e471SBruce Richardson  *       the documentation and/or other materials provided with the
167107e471SBruce Richardson  *       distribution.
177107e471SBruce Richardson  *     * Neither the name of Intel Corporation nor the names of its
187107e471SBruce Richardson  *       contributors may be used to endorse or promote products derived
197107e471SBruce Richardson  *       from this software without specific prior written permission.
207107e471SBruce Richardson  *
217107e471SBruce Richardson  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
227107e471SBruce Richardson  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
237107e471SBruce Richardson  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
247107e471SBruce Richardson  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
257107e471SBruce Richardson  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
267107e471SBruce Richardson  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
277107e471SBruce Richardson  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
287107e471SBruce Richardson  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
297107e471SBruce Richardson  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
307107e471SBruce Richardson  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
317107e471SBruce Richardson  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
327107e471SBruce Richardson  */
337107e471SBruce Richardson 
347107e471SBruce Richardson #include <stdint.h>
357107e471SBruce Richardson #include <inttypes.h>
367107e471SBruce Richardson #include <rte_eal.h>
377107e471SBruce Richardson #include <rte_ethdev.h>
387107e471SBruce Richardson #include <rte_cycles.h>
397107e471SBruce Richardson #include <rte_lcore.h>
407107e471SBruce Richardson #include <rte_mbuf.h>
417107e471SBruce Richardson 
427107e471SBruce Richardson #define RX_RING_SIZE 128
437107e471SBruce Richardson #define TX_RING_SIZE 512
447107e471SBruce Richardson 
457107e471SBruce Richardson #define NUM_MBUFS 8191
467107e471SBruce Richardson #define MBUF_SIZE (1600 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
477107e471SBruce Richardson #define MBUF_CACHE_SIZE 250
487107e471SBruce Richardson #define BURST_SIZE 32
497107e471SBruce Richardson 
507107e471SBruce Richardson static const struct rte_eth_conf port_conf_default = {
517107e471SBruce Richardson 	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, },
527107e471SBruce Richardson };
537107e471SBruce Richardson 
547107e471SBruce Richardson /*
557107e471SBruce Richardson  * Initialises a given port using global settings and with the rx buffers
567107e471SBruce Richardson  * coming from the mbuf_pool passed as parameter
577107e471SBruce Richardson  */
587107e471SBruce Richardson static inline int
597107e471SBruce Richardson port_init(uint8_t port, struct rte_mempool *mbuf_pool)
607107e471SBruce Richardson {
617107e471SBruce Richardson 	struct rte_eth_conf port_conf = port_conf_default;
627107e471SBruce Richardson 	const uint16_t rx_rings = 1, tx_rings = 1;
637107e471SBruce Richardson 	int retval;
647107e471SBruce Richardson 	uint16_t q;
657107e471SBruce Richardson 
667107e471SBruce Richardson 	if (port >= rte_eth_dev_count())
677107e471SBruce Richardson 		return -1;
687107e471SBruce Richardson 
697107e471SBruce Richardson 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
707107e471SBruce Richardson 	if (retval != 0)
717107e471SBruce Richardson 		return retval;
727107e471SBruce Richardson 
737107e471SBruce Richardson 	for (q = 0; q < rx_rings; q++) {
747107e471SBruce Richardson 		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
757107e471SBruce Richardson 				rte_eth_dev_socket_id(port), NULL, mbuf_pool);
767107e471SBruce Richardson 		if (retval < 0)
777107e471SBruce Richardson 			return retval;
787107e471SBruce Richardson 	}
797107e471SBruce Richardson 
807107e471SBruce Richardson 	for (q = 0; q < tx_rings; q++) {
817107e471SBruce Richardson 		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
827107e471SBruce Richardson 				rte_eth_dev_socket_id(port), NULL);
837107e471SBruce Richardson 		if (retval < 0)
847107e471SBruce Richardson 			return retval;
857107e471SBruce Richardson 	}
867107e471SBruce Richardson 
877107e471SBruce Richardson 	retval  = rte_eth_dev_start(port);
887107e471SBruce Richardson 	if (retval < 0)
897107e471SBruce Richardson 		return retval;
907107e471SBruce Richardson 
917107e471SBruce Richardson 	struct ether_addr addr;
927107e471SBruce Richardson 	rte_eth_macaddr_get(port, &addr);
937107e471SBruce Richardson 	printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
947107e471SBruce Richardson 			" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
957107e471SBruce Richardson 			(unsigned)port,
967107e471SBruce Richardson 			addr.addr_bytes[0], addr.addr_bytes[1],
977107e471SBruce Richardson 			addr.addr_bytes[2], addr.addr_bytes[3],
987107e471SBruce Richardson 			addr.addr_bytes[4], addr.addr_bytes[5]);
997107e471SBruce Richardson 
1007107e471SBruce Richardson 	rte_eth_promiscuous_enable(port);
1017107e471SBruce Richardson 
1027107e471SBruce Richardson 	return 0;
1037107e471SBruce Richardson }
1047107e471SBruce Richardson 
1057107e471SBruce Richardson /*
1067107e471SBruce Richardson  * Main thread that does the work, reading from INPUT_PORT
1077107e471SBruce Richardson  * and writing to OUTPUT_PORT
1087107e471SBruce Richardson  */
1097107e471SBruce Richardson static  __attribute__((noreturn)) void
1107107e471SBruce Richardson lcore_main(void)
1117107e471SBruce Richardson {
1127107e471SBruce Richardson 	const uint8_t nb_ports = rte_eth_dev_count();
1137107e471SBruce Richardson 	uint8_t port;
1147107e471SBruce Richardson 	for (port = 0; port < nb_ports; port++)
1157107e471SBruce Richardson 		if (rte_eth_dev_socket_id(port) > 0 &&
1167107e471SBruce Richardson 				rte_eth_dev_socket_id(port) !=
1177107e471SBruce Richardson 						(int)rte_socket_id())
1187107e471SBruce Richardson 			printf("WARNING, port %u is on remote NUMA node to "
1197107e471SBruce Richardson 					"polling thread.\n\tPerformance will "
1207107e471SBruce Richardson 					"not be optimal.\n", port);
1217107e471SBruce Richardson 
1227107e471SBruce Richardson 	printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
1237107e471SBruce Richardson 			rte_lcore_id());
1247107e471SBruce Richardson 	for (;;) {
1257107e471SBruce Richardson 		for (port = 0; port < nb_ports; port++) {
1267107e471SBruce Richardson 			struct rte_mbuf *bufs[BURST_SIZE];
1277107e471SBruce Richardson 			const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
1287107e471SBruce Richardson 					bufs, BURST_SIZE);
1297107e471SBruce Richardson 			if (unlikely(nb_rx == 0))
1307107e471SBruce Richardson 				continue;
1317107e471SBruce Richardson 			const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
1327107e471SBruce Richardson 					bufs, nb_rx);
1337107e471SBruce Richardson 			if (unlikely(nb_tx < nb_rx)) {
1347107e471SBruce Richardson 				uint16_t buf;
1357107e471SBruce Richardson 				for (buf = nb_tx; buf < nb_rx; buf++)
1367107e471SBruce Richardson 					rte_pktmbuf_free(bufs[buf]);
1377107e471SBruce Richardson 			}
1387107e471SBruce Richardson 		}
1397107e471SBruce Richardson 	}
1407107e471SBruce Richardson }
1417107e471SBruce Richardson 
1427107e471SBruce Richardson /* Main function, does initialisation and calls the per-lcore functions */
1437107e471SBruce Richardson int
144*98a16481SDavid Marchand main(int argc, char *argv[])
1457107e471SBruce Richardson {
1467107e471SBruce Richardson 	struct rte_mempool *mbuf_pool;
1477107e471SBruce Richardson 	unsigned nb_ports;
1487107e471SBruce Richardson 	uint8_t portid;
1497107e471SBruce Richardson 
1507107e471SBruce Richardson 	/* init EAL */
1517107e471SBruce Richardson 	int ret = rte_eal_init(argc, argv);
1527107e471SBruce Richardson 	if (ret < 0)
1537107e471SBruce Richardson 		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1547107e471SBruce Richardson 	argc -= ret;
1557107e471SBruce Richardson 	argv += ret;
1567107e471SBruce Richardson 
1577107e471SBruce Richardson 	nb_ports = rte_eth_dev_count();
1587107e471SBruce Richardson 	if (nb_ports < 2 || (nb_ports & 1))
1597107e471SBruce Richardson 		rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
1607107e471SBruce Richardson 
1617107e471SBruce Richardson 	mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
1627107e471SBruce Richardson 				       MBUF_SIZE, MBUF_CACHE_SIZE,
1637107e471SBruce Richardson 				       sizeof(struct rte_pktmbuf_pool_private),
1647107e471SBruce Richardson 				       rte_pktmbuf_pool_init, NULL,
1657107e471SBruce Richardson 				       rte_pktmbuf_init, NULL,
1667107e471SBruce Richardson 				       rte_socket_id(), 0);
1677107e471SBruce Richardson 	if (mbuf_pool == NULL)
1687107e471SBruce Richardson 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
1697107e471SBruce Richardson 
1707107e471SBruce Richardson 	/* initialize all ports */
1717107e471SBruce Richardson 	for (portid = 0; portid < nb_ports; portid++)
1727107e471SBruce Richardson 		if (port_init(portid, mbuf_pool) != 0)
1737107e471SBruce Richardson 			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n",
1747107e471SBruce Richardson 					portid);
1757107e471SBruce Richardson 
1767107e471SBruce Richardson 	if (rte_lcore_count() > 1)
1777107e471SBruce Richardson 		printf("\nWARNING: Too much enabled lcores - App uses only 1 lcore\n");
1787107e471SBruce Richardson 
1797107e471SBruce Richardson 	/* call lcore_main on master core only */
1807107e471SBruce Richardson 	lcore_main();
1817107e471SBruce Richardson 	return 0;
1827107e471SBruce Richardson }
183