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