1*e107e82eSAnatoly Burakov /*- 2*e107e82eSAnatoly Burakov * BSD LICENSE 3*e107e82eSAnatoly Burakov * 4*e107e82eSAnatoly Burakov * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5*e107e82eSAnatoly Burakov * All rights reserved. 6*e107e82eSAnatoly Burakov * 7*e107e82eSAnatoly Burakov * Redistribution and use in source and binary forms, with or without 8*e107e82eSAnatoly Burakov * modification, are permitted provided that the following conditions 9*e107e82eSAnatoly Burakov * are met: 10*e107e82eSAnatoly Burakov * 11*e107e82eSAnatoly Burakov * * Redistributions of source code must retain the above copyright 12*e107e82eSAnatoly Burakov * notice, this list of conditions and the following disclaimer. 13*e107e82eSAnatoly Burakov * * Redistributions in binary form must reproduce the above copyright 14*e107e82eSAnatoly Burakov * notice, this list of conditions and the following disclaimer in 15*e107e82eSAnatoly Burakov * the documentation and/or other materials provided with the 16*e107e82eSAnatoly Burakov * distribution. 17*e107e82eSAnatoly Burakov * * Neither the name of Intel Corporation nor the names of its 18*e107e82eSAnatoly Burakov * contributors may be used to endorse or promote products derived 19*e107e82eSAnatoly Burakov * from this software without specific prior written permission. 20*e107e82eSAnatoly Burakov * 21*e107e82eSAnatoly Burakov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*e107e82eSAnatoly Burakov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*e107e82eSAnatoly Burakov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*e107e82eSAnatoly Burakov * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*e107e82eSAnatoly Burakov * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*e107e82eSAnatoly Burakov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*e107e82eSAnatoly Burakov * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*e107e82eSAnatoly Burakov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*e107e82eSAnatoly Burakov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*e107e82eSAnatoly Burakov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*e107e82eSAnatoly Burakov * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*e107e82eSAnatoly Burakov */ 33*e107e82eSAnatoly Burakov 34*e107e82eSAnatoly Burakov #include <stdio.h> 35*e107e82eSAnatoly Burakov #include <stdlib.h> 36*e107e82eSAnatoly Burakov #include <stdint.h> 37*e107e82eSAnatoly Burakov #include <inttypes.h> 38*e107e82eSAnatoly Burakov #include <sys/types.h> 39*e107e82eSAnatoly Burakov #include <sys/param.h> 40*e107e82eSAnatoly Burakov #include <string.h> 41*e107e82eSAnatoly Burakov #include <sys/queue.h> 42*e107e82eSAnatoly Burakov #include <stdarg.h> 43*e107e82eSAnatoly Burakov #include <errno.h> 44*e107e82eSAnatoly Burakov #include <getopt.h> 45*e107e82eSAnatoly Burakov 46*e107e82eSAnatoly Burakov #include <rte_common.h> 47*e107e82eSAnatoly Burakov #include <rte_byteorder.h> 48*e107e82eSAnatoly Burakov #include <rte_log.h> 49*e107e82eSAnatoly Burakov #include <rte_memory.h> 50*e107e82eSAnatoly Burakov #include <rte_memcpy.h> 51*e107e82eSAnatoly Burakov #include <rte_memzone.h> 52*e107e82eSAnatoly Burakov #include <rte_tailq.h> 53*e107e82eSAnatoly Burakov #include <rte_eal.h> 54*e107e82eSAnatoly Burakov #include <rte_per_lcore.h> 55*e107e82eSAnatoly Burakov #include <rte_launch.h> 56*e107e82eSAnatoly Burakov #include <rte_atomic.h> 57*e107e82eSAnatoly Burakov #include <rte_cycles.h> 58*e107e82eSAnatoly Burakov #include <rte_prefetch.h> 59*e107e82eSAnatoly Burakov #include <rte_lcore.h> 60*e107e82eSAnatoly Burakov #include <rte_per_lcore.h> 61*e107e82eSAnatoly Burakov #include <rte_branch_prediction.h> 62*e107e82eSAnatoly Burakov #include <rte_interrupts.h> 63*e107e82eSAnatoly Burakov #include <rte_pci.h> 64*e107e82eSAnatoly Burakov #include <rte_random.h> 65*e107e82eSAnatoly Burakov #include <rte_debug.h> 66*e107e82eSAnatoly Burakov #include <rte_ether.h> 67*e107e82eSAnatoly Burakov #include <rte_ethdev.h> 68*e107e82eSAnatoly Burakov #include <rte_ring.h> 69*e107e82eSAnatoly Burakov #include <rte_mempool.h> 70*e107e82eSAnatoly Burakov #include <rte_mbuf.h> 71*e107e82eSAnatoly Burakov #include <rte_lpm.h> 72*e107e82eSAnatoly Burakov #include <rte_ip.h> 73*e107e82eSAnatoly Burakov 74*e107e82eSAnatoly Burakov #include "rte_ip_frag.h" 75*e107e82eSAnatoly Burakov #include "main.h" 76*e107e82eSAnatoly Burakov 77*e107e82eSAnatoly Burakov /* 78*e107e82eSAnatoly Burakov * Default byte size for the IPv4 Maximum Transfer Unit (MTU). 79*e107e82eSAnatoly Burakov * This value includes the size of IPv4 header. 80*e107e82eSAnatoly Burakov */ 81*e107e82eSAnatoly Burakov #define IPV4_MTU_DEFAULT ETHER_MTU 82*e107e82eSAnatoly Burakov 83*e107e82eSAnatoly Burakov /* 84*e107e82eSAnatoly Burakov * Default payload in bytes for the IPv4 packet. 85*e107e82eSAnatoly Burakov */ 86*e107e82eSAnatoly Burakov #define IPV4_DEFAULT_PAYLOAD (IPV4_MTU_DEFAULT - sizeof(struct ipv4_hdr)) 87*e107e82eSAnatoly Burakov 88*e107e82eSAnatoly Burakov #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 89*e107e82eSAnatoly Burakov 90*e107e82eSAnatoly Burakov #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 91*e107e82eSAnatoly Burakov 92*e107e82eSAnatoly Burakov /* allow max jumbo frame 9.5 KB */ 93*e107e82eSAnatoly Burakov #define JUMBO_FRAME_MAX_SIZE 0x2600 94*e107e82eSAnatoly Burakov 95*e107e82eSAnatoly Burakov #define ROUNDUP_DIV(a, b) (((a) + (b) - 1) / (b)) 96*e107e82eSAnatoly Burakov 97*e107e82eSAnatoly Burakov /* 98*e107e82eSAnatoly Burakov * Max number of fragments per packet expected. 99*e107e82eSAnatoly Burakov */ 100*e107e82eSAnatoly Burakov #define MAX_PACKET_FRAG ROUNDUP_DIV(JUMBO_FRAME_MAX_SIZE, IPV4_DEFAULT_PAYLOAD) 101*e107e82eSAnatoly Burakov 102*e107e82eSAnatoly Burakov #define NB_MBUF 8192 103*e107e82eSAnatoly Burakov 104*e107e82eSAnatoly Burakov /* 105*e107e82eSAnatoly Burakov * RX and TX Prefetch, Host, and Write-back threshold values should be 106*e107e82eSAnatoly Burakov * carefully set for optimal performance. Consult the network 107*e107e82eSAnatoly Burakov * controller's datasheet and supporting DPDK documentation for guidance 108*e107e82eSAnatoly Burakov * on how these parameters should be set. 109*e107e82eSAnatoly Burakov */ 110*e107e82eSAnatoly Burakov #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ 111*e107e82eSAnatoly Burakov #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ 112*e107e82eSAnatoly Burakov #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ 113*e107e82eSAnatoly Burakov 114*e107e82eSAnatoly Burakov /* 115*e107e82eSAnatoly Burakov * These default values are optimized for use with the Intel(R) 82599 10 GbE 116*e107e82eSAnatoly Burakov * Controller and the DPDK ixgbe PMD. Consider using other values for other 117*e107e82eSAnatoly Burakov * network controllers and/or network drivers. 118*e107e82eSAnatoly Burakov */ 119*e107e82eSAnatoly Burakov #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ 120*e107e82eSAnatoly Burakov #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ 121*e107e82eSAnatoly Burakov #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ 122*e107e82eSAnatoly Burakov 123*e107e82eSAnatoly Burakov #define MAX_PKT_BURST 32 124*e107e82eSAnatoly Burakov #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 125*e107e82eSAnatoly Burakov 126*e107e82eSAnatoly Burakov /* Configure how many packets ahead to prefetch, when reading packets */ 127*e107e82eSAnatoly Burakov #define PREFETCH_OFFSET 3 128*e107e82eSAnatoly Burakov 129*e107e82eSAnatoly Burakov /* 130*e107e82eSAnatoly Burakov * Configurable number of RX/TX ring descriptors 131*e107e82eSAnatoly Burakov */ 132*e107e82eSAnatoly Burakov #define RTE_TEST_RX_DESC_DEFAULT 128 133*e107e82eSAnatoly Burakov #define RTE_TEST_TX_DESC_DEFAULT 512 134*e107e82eSAnatoly Burakov static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 135*e107e82eSAnatoly Burakov static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 136*e107e82eSAnatoly Burakov 137*e107e82eSAnatoly Burakov /* ethernet addresses of ports */ 138*e107e82eSAnatoly Burakov static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 139*e107e82eSAnatoly Burakov static struct ether_addr remote_eth_addr = 140*e107e82eSAnatoly Burakov {{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; 141*e107e82eSAnatoly Burakov 142*e107e82eSAnatoly Burakov /* mask of enabled ports */ 143*e107e82eSAnatoly Burakov static int enabled_port_mask = 0; 144*e107e82eSAnatoly Burakov 145*e107e82eSAnatoly Burakov static int rx_queue_per_lcore = 1; 146*e107e82eSAnatoly Burakov 147*e107e82eSAnatoly Burakov #define MBUF_TABLE_SIZE (2 * MAX(MAX_PKT_BURST, MAX_PACKET_FRAG)) 148*e107e82eSAnatoly Burakov 149*e107e82eSAnatoly Burakov struct mbuf_table { 150*e107e82eSAnatoly Burakov uint16_t len; 151*e107e82eSAnatoly Burakov struct rte_mbuf *m_table[MBUF_TABLE_SIZE]; 152*e107e82eSAnatoly Burakov }; 153*e107e82eSAnatoly Burakov 154*e107e82eSAnatoly Burakov #define MAX_RX_QUEUE_PER_LCORE 16 155*e107e82eSAnatoly Burakov #define MAX_TX_QUEUE_PER_PORT 16 156*e107e82eSAnatoly Burakov struct lcore_queue_conf { 157*e107e82eSAnatoly Burakov uint16_t n_rx_queue; 158*e107e82eSAnatoly Burakov uint8_t rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 159*e107e82eSAnatoly Burakov uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 160*e107e82eSAnatoly Burakov struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; 161*e107e82eSAnatoly Burakov 162*e107e82eSAnatoly Burakov } __rte_cache_aligned; 163*e107e82eSAnatoly Burakov struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; 164*e107e82eSAnatoly Burakov 165*e107e82eSAnatoly Burakov static const struct rte_eth_conf port_conf = { 166*e107e82eSAnatoly Burakov .rxmode = { 167*e107e82eSAnatoly Burakov .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, 168*e107e82eSAnatoly Burakov .split_hdr_size = 0, 169*e107e82eSAnatoly Burakov .header_split = 0, /**< Header Split disabled */ 170*e107e82eSAnatoly Burakov .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 171*e107e82eSAnatoly Burakov .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 172*e107e82eSAnatoly Burakov .jumbo_frame = 1, /**< Jumbo Frame Support enabled */ 173*e107e82eSAnatoly Burakov .hw_strip_crc = 0, /**< CRC stripped by hardware */ 174*e107e82eSAnatoly Burakov }, 175*e107e82eSAnatoly Burakov .txmode = { 176*e107e82eSAnatoly Burakov .mq_mode = ETH_MQ_TX_NONE, 177*e107e82eSAnatoly Burakov }, 178*e107e82eSAnatoly Burakov }; 179*e107e82eSAnatoly Burakov 180*e107e82eSAnatoly Burakov static const struct rte_eth_rxconf rx_conf = { 181*e107e82eSAnatoly Burakov .rx_thresh = { 182*e107e82eSAnatoly Burakov .pthresh = RX_PTHRESH, 183*e107e82eSAnatoly Burakov .hthresh = RX_HTHRESH, 184*e107e82eSAnatoly Burakov .wthresh = RX_WTHRESH, 185*e107e82eSAnatoly Burakov }, 186*e107e82eSAnatoly Burakov }; 187*e107e82eSAnatoly Burakov 188*e107e82eSAnatoly Burakov static const struct rte_eth_txconf tx_conf = { 189*e107e82eSAnatoly Burakov .tx_thresh = { 190*e107e82eSAnatoly Burakov .pthresh = TX_PTHRESH, 191*e107e82eSAnatoly Burakov .hthresh = TX_HTHRESH, 192*e107e82eSAnatoly Burakov .wthresh = TX_WTHRESH, 193*e107e82eSAnatoly Burakov }, 194*e107e82eSAnatoly Burakov .tx_free_thresh = 0, /* Use PMD default values */ 195*e107e82eSAnatoly Burakov .tx_rs_thresh = 0, /* Use PMD default values */ 196*e107e82eSAnatoly Burakov }; 197*e107e82eSAnatoly Burakov 198*e107e82eSAnatoly Burakov struct rte_mempool *pool_direct = NULL, *pool_indirect = NULL; 199*e107e82eSAnatoly Burakov 200*e107e82eSAnatoly Burakov struct l3fwd_route { 201*e107e82eSAnatoly Burakov uint32_t ip; 202*e107e82eSAnatoly Burakov uint8_t depth; 203*e107e82eSAnatoly Burakov uint8_t if_out; 204*e107e82eSAnatoly Burakov }; 205*e107e82eSAnatoly Burakov 206*e107e82eSAnatoly Burakov struct l3fwd_route l3fwd_route_array[] = { 207*e107e82eSAnatoly Burakov {IPv4(100,10,0,0), 16, 2}, 208*e107e82eSAnatoly Burakov {IPv4(100,20,0,0), 16, 2}, 209*e107e82eSAnatoly Burakov {IPv4(100,30,0,0), 16, 0}, 210*e107e82eSAnatoly Burakov {IPv4(100,40,0,0), 16, 0}, 211*e107e82eSAnatoly Burakov }; 212*e107e82eSAnatoly Burakov 213*e107e82eSAnatoly Burakov #define L3FWD_NUM_ROUTES \ 214*e107e82eSAnatoly Burakov (sizeof(l3fwd_route_array) / sizeof(l3fwd_route_array[0])) 215*e107e82eSAnatoly Burakov 216*e107e82eSAnatoly Burakov #define L3FWD_LPM_MAX_RULES 1024 217*e107e82eSAnatoly Burakov 218*e107e82eSAnatoly Burakov struct rte_lpm *l3fwd_lpm = NULL; 219*e107e82eSAnatoly Burakov 220*e107e82eSAnatoly Burakov /* Send burst of packets on an output interface */ 221*e107e82eSAnatoly Burakov static inline int 222*e107e82eSAnatoly Burakov send_burst(struct lcore_queue_conf *qconf, uint16_t n, uint8_t port) 223*e107e82eSAnatoly Burakov { 224*e107e82eSAnatoly Burakov struct rte_mbuf **m_table; 225*e107e82eSAnatoly Burakov int ret; 226*e107e82eSAnatoly Burakov uint16_t queueid; 227*e107e82eSAnatoly Burakov 228*e107e82eSAnatoly Burakov queueid = qconf->tx_queue_id[port]; 229*e107e82eSAnatoly Burakov m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; 230*e107e82eSAnatoly Burakov 231*e107e82eSAnatoly Burakov ret = rte_eth_tx_burst(port, queueid, m_table, n); 232*e107e82eSAnatoly Burakov if (unlikely(ret < n)) { 233*e107e82eSAnatoly Burakov do { 234*e107e82eSAnatoly Burakov rte_pktmbuf_free(m_table[ret]); 235*e107e82eSAnatoly Burakov } while (++ret < n); 236*e107e82eSAnatoly Burakov } 237*e107e82eSAnatoly Burakov 238*e107e82eSAnatoly Burakov return 0; 239*e107e82eSAnatoly Burakov } 240*e107e82eSAnatoly Burakov 241*e107e82eSAnatoly Burakov static inline void 242*e107e82eSAnatoly Burakov l3fwd_simple_forward(struct rte_mbuf *m, uint8_t port_in) 243*e107e82eSAnatoly Burakov { 244*e107e82eSAnatoly Burakov struct lcore_queue_conf *qconf; 245*e107e82eSAnatoly Burakov struct ipv4_hdr *ip_hdr; 246*e107e82eSAnatoly Burakov uint32_t i, len, lcore_id, ip_dst; 247*e107e82eSAnatoly Burakov uint8_t next_hop, port_out; 248*e107e82eSAnatoly Burakov int32_t len2; 249*e107e82eSAnatoly Burakov 250*e107e82eSAnatoly Burakov lcore_id = rte_lcore_id(); 251*e107e82eSAnatoly Burakov qconf = &lcore_queue_conf[lcore_id]; 252*e107e82eSAnatoly Burakov 253*e107e82eSAnatoly Burakov /* Remove the Ethernet header and trailer from the input packet */ 254*e107e82eSAnatoly Burakov rte_pktmbuf_adj(m, (uint16_t)sizeof(struct ether_hdr)); 255*e107e82eSAnatoly Burakov 256*e107e82eSAnatoly Burakov /* Read the lookup key (i.e. ip_dst) from the input packet */ 257*e107e82eSAnatoly Burakov ip_hdr = rte_pktmbuf_mtod(m, struct ipv4_hdr *); 258*e107e82eSAnatoly Burakov ip_dst = rte_be_to_cpu_32(ip_hdr->dst_addr); 259*e107e82eSAnatoly Burakov 260*e107e82eSAnatoly Burakov /* Find destination port */ 261*e107e82eSAnatoly Burakov if (rte_lpm_lookup(l3fwd_lpm, ip_dst, &next_hop) == 0 && 262*e107e82eSAnatoly Burakov (enabled_port_mask & 1 << next_hop) != 0) 263*e107e82eSAnatoly Burakov port_out = next_hop; 264*e107e82eSAnatoly Burakov else 265*e107e82eSAnatoly Burakov port_out = port_in; 266*e107e82eSAnatoly Burakov 267*e107e82eSAnatoly Burakov /* Build transmission burst */ 268*e107e82eSAnatoly Burakov len = qconf->tx_mbufs[port_out].len; 269*e107e82eSAnatoly Burakov 270*e107e82eSAnatoly Burakov /* if we don't need to do any fragmentation */ 271*e107e82eSAnatoly Burakov if (likely (IPV4_MTU_DEFAULT >= m->pkt.pkt_len)) { 272*e107e82eSAnatoly Burakov qconf->tx_mbufs[port_out].m_table[len] = m; 273*e107e82eSAnatoly Burakov len2 = 1; 274*e107e82eSAnatoly Burakov } else { 275*e107e82eSAnatoly Burakov len2 = rte_ipv4_fragment_packet(m, 276*e107e82eSAnatoly Burakov &qconf->tx_mbufs[port_out].m_table[len], 277*e107e82eSAnatoly Burakov (uint16_t)(MBUF_TABLE_SIZE - len), 278*e107e82eSAnatoly Burakov IPV4_MTU_DEFAULT, 279*e107e82eSAnatoly Burakov pool_direct, pool_indirect); 280*e107e82eSAnatoly Burakov 281*e107e82eSAnatoly Burakov /* Free input packet */ 282*e107e82eSAnatoly Burakov rte_pktmbuf_free(m); 283*e107e82eSAnatoly Burakov 284*e107e82eSAnatoly Burakov /* If we fail to fragment the packet */ 285*e107e82eSAnatoly Burakov if (unlikely (len2 < 0)) 286*e107e82eSAnatoly Burakov return; 287*e107e82eSAnatoly Burakov } 288*e107e82eSAnatoly Burakov 289*e107e82eSAnatoly Burakov for (i = len; i < len + len2; i ++) { 290*e107e82eSAnatoly Burakov m = qconf->tx_mbufs[port_out].m_table[i]; 291*e107e82eSAnatoly Burakov struct ether_hdr *eth_hdr = (struct ether_hdr *) 292*e107e82eSAnatoly Burakov rte_pktmbuf_prepend(m, (uint16_t)sizeof(struct ether_hdr)); 293*e107e82eSAnatoly Burakov if (eth_hdr == NULL) { 294*e107e82eSAnatoly Burakov rte_panic("No headroom in mbuf.\n"); 295*e107e82eSAnatoly Burakov } 296*e107e82eSAnatoly Burakov 297*e107e82eSAnatoly Burakov m->pkt.vlan_macip.f.l2_len = sizeof(struct ether_hdr); 298*e107e82eSAnatoly Burakov 299*e107e82eSAnatoly Burakov ether_addr_copy(&remote_eth_addr, ð_hdr->d_addr); 300*e107e82eSAnatoly Burakov ether_addr_copy(&ports_eth_addr[port_out], ð_hdr->s_addr); 301*e107e82eSAnatoly Burakov eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); 302*e107e82eSAnatoly Burakov } 303*e107e82eSAnatoly Burakov 304*e107e82eSAnatoly Burakov len += len2; 305*e107e82eSAnatoly Burakov 306*e107e82eSAnatoly Burakov if (likely(len < MAX_PKT_BURST)) { 307*e107e82eSAnatoly Burakov qconf->tx_mbufs[port_out].len = (uint16_t)len; 308*e107e82eSAnatoly Burakov return; 309*e107e82eSAnatoly Burakov } 310*e107e82eSAnatoly Burakov 311*e107e82eSAnatoly Burakov /* Transmit packets */ 312*e107e82eSAnatoly Burakov send_burst(qconf, (uint16_t)len, port_out); 313*e107e82eSAnatoly Burakov qconf->tx_mbufs[port_out].len = 0; 314*e107e82eSAnatoly Burakov } 315*e107e82eSAnatoly Burakov 316*e107e82eSAnatoly Burakov /* main processing loop */ 317*e107e82eSAnatoly Burakov static int 318*e107e82eSAnatoly Burakov main_loop(__attribute__((unused)) void *dummy) 319*e107e82eSAnatoly Burakov { 320*e107e82eSAnatoly Burakov struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 321*e107e82eSAnatoly Burakov unsigned lcore_id; 322*e107e82eSAnatoly Burakov uint64_t prev_tsc, diff_tsc, cur_tsc; 323*e107e82eSAnatoly Burakov int i, j, nb_rx; 324*e107e82eSAnatoly Burakov uint8_t portid; 325*e107e82eSAnatoly Burakov struct lcore_queue_conf *qconf; 326*e107e82eSAnatoly Burakov const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; 327*e107e82eSAnatoly Burakov 328*e107e82eSAnatoly Burakov prev_tsc = 0; 329*e107e82eSAnatoly Burakov 330*e107e82eSAnatoly Burakov lcore_id = rte_lcore_id(); 331*e107e82eSAnatoly Burakov qconf = &lcore_queue_conf[lcore_id]; 332*e107e82eSAnatoly Burakov 333*e107e82eSAnatoly Burakov if (qconf->n_rx_queue == 0) { 334*e107e82eSAnatoly Burakov RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); 335*e107e82eSAnatoly Burakov return 0; 336*e107e82eSAnatoly Burakov } 337*e107e82eSAnatoly Burakov 338*e107e82eSAnatoly Burakov RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); 339*e107e82eSAnatoly Burakov 340*e107e82eSAnatoly Burakov for (i = 0; i < qconf->n_rx_queue; i++) { 341*e107e82eSAnatoly Burakov 342*e107e82eSAnatoly Burakov portid = qconf->rx_queue_list[i]; 343*e107e82eSAnatoly Burakov RTE_LOG(INFO, L3FWD, " -- lcoreid=%u portid=%d\n", lcore_id, 344*e107e82eSAnatoly Burakov (int) portid); 345*e107e82eSAnatoly Burakov } 346*e107e82eSAnatoly Burakov 347*e107e82eSAnatoly Burakov while (1) { 348*e107e82eSAnatoly Burakov 349*e107e82eSAnatoly Burakov cur_tsc = rte_rdtsc(); 350*e107e82eSAnatoly Burakov 351*e107e82eSAnatoly Burakov /* 352*e107e82eSAnatoly Burakov * TX burst queue drain 353*e107e82eSAnatoly Burakov */ 354*e107e82eSAnatoly Burakov diff_tsc = cur_tsc - prev_tsc; 355*e107e82eSAnatoly Burakov if (unlikely(diff_tsc > drain_tsc)) { 356*e107e82eSAnatoly Burakov 357*e107e82eSAnatoly Burakov /* 358*e107e82eSAnatoly Burakov * This could be optimized (use queueid instead of 359*e107e82eSAnatoly Burakov * portid), but it is not called so often 360*e107e82eSAnatoly Burakov */ 361*e107e82eSAnatoly Burakov for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 362*e107e82eSAnatoly Burakov if (qconf->tx_mbufs[portid].len == 0) 363*e107e82eSAnatoly Burakov continue; 364*e107e82eSAnatoly Burakov send_burst(&lcore_queue_conf[lcore_id], 365*e107e82eSAnatoly Burakov qconf->tx_mbufs[portid].len, 366*e107e82eSAnatoly Burakov portid); 367*e107e82eSAnatoly Burakov qconf->tx_mbufs[portid].len = 0; 368*e107e82eSAnatoly Burakov } 369*e107e82eSAnatoly Burakov 370*e107e82eSAnatoly Burakov prev_tsc = cur_tsc; 371*e107e82eSAnatoly Burakov } 372*e107e82eSAnatoly Burakov 373*e107e82eSAnatoly Burakov /* 374*e107e82eSAnatoly Burakov * Read packet from RX queues 375*e107e82eSAnatoly Burakov */ 376*e107e82eSAnatoly Burakov for (i = 0; i < qconf->n_rx_queue; i++) { 377*e107e82eSAnatoly Burakov 378*e107e82eSAnatoly Burakov portid = qconf->rx_queue_list[i]; 379*e107e82eSAnatoly Burakov nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, 380*e107e82eSAnatoly Burakov MAX_PKT_BURST); 381*e107e82eSAnatoly Burakov 382*e107e82eSAnatoly Burakov /* Prefetch first packets */ 383*e107e82eSAnatoly Burakov for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 384*e107e82eSAnatoly Burakov rte_prefetch0(rte_pktmbuf_mtod( 385*e107e82eSAnatoly Burakov pkts_burst[j], void *)); 386*e107e82eSAnatoly Burakov } 387*e107e82eSAnatoly Burakov 388*e107e82eSAnatoly Burakov /* Prefetch and forward already prefetched packets */ 389*e107e82eSAnatoly Burakov for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 390*e107e82eSAnatoly Burakov rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 391*e107e82eSAnatoly Burakov j + PREFETCH_OFFSET], void *)); 392*e107e82eSAnatoly Burakov l3fwd_simple_forward(pkts_burst[j], portid); 393*e107e82eSAnatoly Burakov } 394*e107e82eSAnatoly Burakov 395*e107e82eSAnatoly Burakov /* Forward remaining prefetched packets */ 396*e107e82eSAnatoly Burakov for (; j < nb_rx; j++) { 397*e107e82eSAnatoly Burakov l3fwd_simple_forward(pkts_burst[j], portid); 398*e107e82eSAnatoly Burakov } 399*e107e82eSAnatoly Burakov } 400*e107e82eSAnatoly Burakov } 401*e107e82eSAnatoly Burakov } 402*e107e82eSAnatoly Burakov 403*e107e82eSAnatoly Burakov /* display usage */ 404*e107e82eSAnatoly Burakov static void 405*e107e82eSAnatoly Burakov print_usage(const char *prgname) 406*e107e82eSAnatoly Burakov { 407*e107e82eSAnatoly Burakov printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" 408*e107e82eSAnatoly Burakov " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 409*e107e82eSAnatoly Burakov " -q NQ: number of queue (=ports) per lcore (default is 1)\n", 410*e107e82eSAnatoly Burakov prgname); 411*e107e82eSAnatoly Burakov } 412*e107e82eSAnatoly Burakov 413*e107e82eSAnatoly Burakov static int 414*e107e82eSAnatoly Burakov parse_portmask(const char *portmask) 415*e107e82eSAnatoly Burakov { 416*e107e82eSAnatoly Burakov char *end = NULL; 417*e107e82eSAnatoly Burakov unsigned long pm; 418*e107e82eSAnatoly Burakov 419*e107e82eSAnatoly Burakov /* parse hexadecimal string */ 420*e107e82eSAnatoly Burakov pm = strtoul(portmask, &end, 16); 421*e107e82eSAnatoly Burakov if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 422*e107e82eSAnatoly Burakov return -1; 423*e107e82eSAnatoly Burakov 424*e107e82eSAnatoly Burakov if (pm == 0) 425*e107e82eSAnatoly Burakov return -1; 426*e107e82eSAnatoly Burakov 427*e107e82eSAnatoly Burakov return pm; 428*e107e82eSAnatoly Burakov } 429*e107e82eSAnatoly Burakov 430*e107e82eSAnatoly Burakov static int 431*e107e82eSAnatoly Burakov parse_nqueue(const char *q_arg) 432*e107e82eSAnatoly Burakov { 433*e107e82eSAnatoly Burakov char *end = NULL; 434*e107e82eSAnatoly Burakov unsigned long n; 435*e107e82eSAnatoly Burakov 436*e107e82eSAnatoly Burakov /* parse hexadecimal string */ 437*e107e82eSAnatoly Burakov n = strtoul(q_arg, &end, 10); 438*e107e82eSAnatoly Burakov if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 439*e107e82eSAnatoly Burakov return -1; 440*e107e82eSAnatoly Burakov if (n == 0) 441*e107e82eSAnatoly Burakov return -1; 442*e107e82eSAnatoly Burakov if (n >= MAX_RX_QUEUE_PER_LCORE) 443*e107e82eSAnatoly Burakov return -1; 444*e107e82eSAnatoly Burakov 445*e107e82eSAnatoly Burakov return n; 446*e107e82eSAnatoly Burakov } 447*e107e82eSAnatoly Burakov 448*e107e82eSAnatoly Burakov /* Parse the argument given in the command line of the application */ 449*e107e82eSAnatoly Burakov static int 450*e107e82eSAnatoly Burakov parse_args(int argc, char **argv) 451*e107e82eSAnatoly Burakov { 452*e107e82eSAnatoly Burakov int opt, ret; 453*e107e82eSAnatoly Burakov char **argvopt; 454*e107e82eSAnatoly Burakov int option_index; 455*e107e82eSAnatoly Burakov char *prgname = argv[0]; 456*e107e82eSAnatoly Burakov static struct option lgopts[] = { 457*e107e82eSAnatoly Burakov {NULL, 0, 0, 0} 458*e107e82eSAnatoly Burakov }; 459*e107e82eSAnatoly Burakov 460*e107e82eSAnatoly Burakov argvopt = argv; 461*e107e82eSAnatoly Burakov 462*e107e82eSAnatoly Burakov while ((opt = getopt_long(argc, argvopt, "p:q:", 463*e107e82eSAnatoly Burakov lgopts, &option_index)) != EOF) { 464*e107e82eSAnatoly Burakov 465*e107e82eSAnatoly Burakov switch (opt) { 466*e107e82eSAnatoly Burakov /* portmask */ 467*e107e82eSAnatoly Burakov case 'p': 468*e107e82eSAnatoly Burakov enabled_port_mask = parse_portmask(optarg); 469*e107e82eSAnatoly Burakov if (enabled_port_mask < 0) { 470*e107e82eSAnatoly Burakov printf("invalid portmask\n"); 471*e107e82eSAnatoly Burakov print_usage(prgname); 472*e107e82eSAnatoly Burakov return -1; 473*e107e82eSAnatoly Burakov } 474*e107e82eSAnatoly Burakov break; 475*e107e82eSAnatoly Burakov 476*e107e82eSAnatoly Burakov /* nqueue */ 477*e107e82eSAnatoly Burakov case 'q': 478*e107e82eSAnatoly Burakov rx_queue_per_lcore = parse_nqueue(optarg); 479*e107e82eSAnatoly Burakov if (rx_queue_per_lcore < 0) { 480*e107e82eSAnatoly Burakov printf("invalid queue number\n"); 481*e107e82eSAnatoly Burakov print_usage(prgname); 482*e107e82eSAnatoly Burakov return -1; 483*e107e82eSAnatoly Burakov } 484*e107e82eSAnatoly Burakov break; 485*e107e82eSAnatoly Burakov 486*e107e82eSAnatoly Burakov /* long options */ 487*e107e82eSAnatoly Burakov case 0: 488*e107e82eSAnatoly Burakov print_usage(prgname); 489*e107e82eSAnatoly Burakov return -1; 490*e107e82eSAnatoly Burakov 491*e107e82eSAnatoly Burakov default: 492*e107e82eSAnatoly Burakov print_usage(prgname); 493*e107e82eSAnatoly Burakov return -1; 494*e107e82eSAnatoly Burakov } 495*e107e82eSAnatoly Burakov } 496*e107e82eSAnatoly Burakov 497*e107e82eSAnatoly Burakov if (enabled_port_mask == 0) { 498*e107e82eSAnatoly Burakov printf("portmask not specified\n"); 499*e107e82eSAnatoly Burakov print_usage(prgname); 500*e107e82eSAnatoly Burakov return -1; 501*e107e82eSAnatoly Burakov } 502*e107e82eSAnatoly Burakov 503*e107e82eSAnatoly Burakov if (optind >= 0) 504*e107e82eSAnatoly Burakov argv[optind-1] = prgname; 505*e107e82eSAnatoly Burakov 506*e107e82eSAnatoly Burakov ret = optind-1; 507*e107e82eSAnatoly Burakov optind = 0; /* reset getopt lib */ 508*e107e82eSAnatoly Burakov return ret; 509*e107e82eSAnatoly Burakov } 510*e107e82eSAnatoly Burakov 511*e107e82eSAnatoly Burakov static void 512*e107e82eSAnatoly Burakov print_ethaddr(const char *name, struct ether_addr *eth_addr) 513*e107e82eSAnatoly Burakov { 514*e107e82eSAnatoly Burakov printf("%s%02X:%02X:%02X:%02X:%02X:%02X", name, 515*e107e82eSAnatoly Burakov eth_addr->addr_bytes[0], 516*e107e82eSAnatoly Burakov eth_addr->addr_bytes[1], 517*e107e82eSAnatoly Burakov eth_addr->addr_bytes[2], 518*e107e82eSAnatoly Burakov eth_addr->addr_bytes[3], 519*e107e82eSAnatoly Burakov eth_addr->addr_bytes[4], 520*e107e82eSAnatoly Burakov eth_addr->addr_bytes[5]); 521*e107e82eSAnatoly Burakov } 522*e107e82eSAnatoly Burakov 523*e107e82eSAnatoly Burakov /* Check the link status of all ports in up to 9s, and print them finally */ 524*e107e82eSAnatoly Burakov static void 525*e107e82eSAnatoly Burakov check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 526*e107e82eSAnatoly Burakov { 527*e107e82eSAnatoly Burakov #define CHECK_INTERVAL 100 /* 100ms */ 528*e107e82eSAnatoly Burakov #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 529*e107e82eSAnatoly Burakov uint8_t portid, count, all_ports_up, print_flag = 0; 530*e107e82eSAnatoly Burakov struct rte_eth_link link; 531*e107e82eSAnatoly Burakov 532*e107e82eSAnatoly Burakov printf("\nChecking link status"); 533*e107e82eSAnatoly Burakov fflush(stdout); 534*e107e82eSAnatoly Burakov for (count = 0; count <= MAX_CHECK_TIME; count++) { 535*e107e82eSAnatoly Burakov all_ports_up = 1; 536*e107e82eSAnatoly Burakov for (portid = 0; portid < port_num; portid++) { 537*e107e82eSAnatoly Burakov if ((port_mask & (1 << portid)) == 0) 538*e107e82eSAnatoly Burakov continue; 539*e107e82eSAnatoly Burakov memset(&link, 0, sizeof(link)); 540*e107e82eSAnatoly Burakov rte_eth_link_get_nowait(portid, &link); 541*e107e82eSAnatoly Burakov /* print link status if flag set */ 542*e107e82eSAnatoly Burakov if (print_flag == 1) { 543*e107e82eSAnatoly Burakov if (link.link_status) 544*e107e82eSAnatoly Burakov printf("Port %d Link Up - speed %u " 545*e107e82eSAnatoly Burakov "Mbps - %s\n", (uint8_t)portid, 546*e107e82eSAnatoly Burakov (unsigned)link.link_speed, 547*e107e82eSAnatoly Burakov (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 548*e107e82eSAnatoly Burakov ("full-duplex") : ("half-duplex\n")); 549*e107e82eSAnatoly Burakov else 550*e107e82eSAnatoly Burakov printf("Port %d Link Down\n", 551*e107e82eSAnatoly Burakov (uint8_t)portid); 552*e107e82eSAnatoly Burakov continue; 553*e107e82eSAnatoly Burakov } 554*e107e82eSAnatoly Burakov /* clear all_ports_up flag if any link down */ 555*e107e82eSAnatoly Burakov if (link.link_status == 0) { 556*e107e82eSAnatoly Burakov all_ports_up = 0; 557*e107e82eSAnatoly Burakov break; 558*e107e82eSAnatoly Burakov } 559*e107e82eSAnatoly Burakov } 560*e107e82eSAnatoly Burakov /* after finally printing all link status, get out */ 561*e107e82eSAnatoly Burakov if (print_flag == 1) 562*e107e82eSAnatoly Burakov break; 563*e107e82eSAnatoly Burakov 564*e107e82eSAnatoly Burakov if (all_ports_up == 0) { 565*e107e82eSAnatoly Burakov printf("."); 566*e107e82eSAnatoly Burakov fflush(stdout); 567*e107e82eSAnatoly Burakov rte_delay_ms(CHECK_INTERVAL); 568*e107e82eSAnatoly Burakov } 569*e107e82eSAnatoly Burakov 570*e107e82eSAnatoly Burakov /* set the print_flag if all ports up or timeout */ 571*e107e82eSAnatoly Burakov if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 572*e107e82eSAnatoly Burakov print_flag = 1; 573*e107e82eSAnatoly Burakov printf("done\n"); 574*e107e82eSAnatoly Burakov } 575*e107e82eSAnatoly Burakov } 576*e107e82eSAnatoly Burakov } 577*e107e82eSAnatoly Burakov 578*e107e82eSAnatoly Burakov int 579*e107e82eSAnatoly Burakov MAIN(int argc, char **argv) 580*e107e82eSAnatoly Burakov { 581*e107e82eSAnatoly Burakov struct lcore_queue_conf *qconf; 582*e107e82eSAnatoly Burakov int ret; 583*e107e82eSAnatoly Burakov unsigned nb_ports, i; 584*e107e82eSAnatoly Burakov uint16_t queueid = 0; 585*e107e82eSAnatoly Burakov unsigned lcore_id = 0, rx_lcore_id = 0; 586*e107e82eSAnatoly Burakov uint32_t n_tx_queue, nb_lcores; 587*e107e82eSAnatoly Burakov uint8_t portid; 588*e107e82eSAnatoly Burakov 589*e107e82eSAnatoly Burakov /* init EAL */ 590*e107e82eSAnatoly Burakov ret = rte_eal_init(argc, argv); 591*e107e82eSAnatoly Burakov if (ret < 0) 592*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "rte_eal_init failed"); 593*e107e82eSAnatoly Burakov argc -= ret; 594*e107e82eSAnatoly Burakov argv += ret; 595*e107e82eSAnatoly Burakov 596*e107e82eSAnatoly Burakov /* parse application arguments (after the EAL ones) */ 597*e107e82eSAnatoly Burakov ret = parse_args(argc, argv); 598*e107e82eSAnatoly Burakov if (ret < 0) 599*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "Invalid arguments"); 600*e107e82eSAnatoly Burakov 601*e107e82eSAnatoly Burakov /* create the mbuf pools */ 602*e107e82eSAnatoly Burakov pool_direct = 603*e107e82eSAnatoly Burakov rte_mempool_create("pool_direct", NB_MBUF, 604*e107e82eSAnatoly Burakov MBUF_SIZE, 32, 605*e107e82eSAnatoly Burakov sizeof(struct rte_pktmbuf_pool_private), 606*e107e82eSAnatoly Burakov rte_pktmbuf_pool_init, NULL, 607*e107e82eSAnatoly Burakov rte_pktmbuf_init, NULL, 608*e107e82eSAnatoly Burakov rte_socket_id(), 0); 609*e107e82eSAnatoly Burakov if (pool_direct == NULL) 610*e107e82eSAnatoly Burakov rte_panic("Cannot init direct mbuf pool\n"); 611*e107e82eSAnatoly Burakov 612*e107e82eSAnatoly Burakov pool_indirect = 613*e107e82eSAnatoly Burakov rte_mempool_create("pool_indirect", NB_MBUF, 614*e107e82eSAnatoly Burakov sizeof(struct rte_mbuf), 32, 615*e107e82eSAnatoly Burakov 0, 616*e107e82eSAnatoly Burakov NULL, NULL, 617*e107e82eSAnatoly Burakov rte_pktmbuf_init, NULL, 618*e107e82eSAnatoly Burakov rte_socket_id(), 0); 619*e107e82eSAnatoly Burakov if (pool_indirect == NULL) 620*e107e82eSAnatoly Burakov rte_panic("Cannot init indirect mbuf pool\n"); 621*e107e82eSAnatoly Burakov 622*e107e82eSAnatoly Burakov if (rte_eal_pci_probe() < 0) 623*e107e82eSAnatoly Burakov rte_panic("Cannot probe PCI\n"); 624*e107e82eSAnatoly Burakov 625*e107e82eSAnatoly Burakov nb_ports = rte_eth_dev_count(); 626*e107e82eSAnatoly Burakov if (nb_ports > RTE_MAX_ETHPORTS) 627*e107e82eSAnatoly Burakov nb_ports = RTE_MAX_ETHPORTS; 628*e107e82eSAnatoly Burakov 629*e107e82eSAnatoly Burakov nb_lcores = rte_lcore_count(); 630*e107e82eSAnatoly Burakov 631*e107e82eSAnatoly Burakov /* initialize all ports */ 632*e107e82eSAnatoly Burakov for (portid = 0; portid < nb_ports; portid++) { 633*e107e82eSAnatoly Burakov /* skip ports that are not enabled */ 634*e107e82eSAnatoly Burakov if ((enabled_port_mask & (1 << portid)) == 0) { 635*e107e82eSAnatoly Burakov printf("Skipping disabled port %d\n", portid); 636*e107e82eSAnatoly Burakov continue; 637*e107e82eSAnatoly Burakov } 638*e107e82eSAnatoly Burakov 639*e107e82eSAnatoly Burakov qconf = &lcore_queue_conf[rx_lcore_id]; 640*e107e82eSAnatoly Burakov 641*e107e82eSAnatoly Burakov /* get the lcore_id for this port */ 642*e107e82eSAnatoly Burakov while (rte_lcore_is_enabled(rx_lcore_id) == 0 || 643*e107e82eSAnatoly Burakov qconf->n_rx_queue == (unsigned)rx_queue_per_lcore) { 644*e107e82eSAnatoly Burakov 645*e107e82eSAnatoly Burakov rx_lcore_id ++; 646*e107e82eSAnatoly Burakov if (rx_lcore_id >= RTE_MAX_LCORE) 647*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "Not enough cores\n"); 648*e107e82eSAnatoly Burakov 649*e107e82eSAnatoly Burakov qconf = &lcore_queue_conf[rx_lcore_id]; 650*e107e82eSAnatoly Burakov } 651*e107e82eSAnatoly Burakov qconf->rx_queue_list[qconf->n_rx_queue] = portid; 652*e107e82eSAnatoly Burakov qconf->n_rx_queue++; 653*e107e82eSAnatoly Burakov 654*e107e82eSAnatoly Burakov /* init port */ 655*e107e82eSAnatoly Burakov printf("Initializing port %d on lcore %u... ", portid, 656*e107e82eSAnatoly Burakov rx_lcore_id); 657*e107e82eSAnatoly Burakov fflush(stdout); 658*e107e82eSAnatoly Burakov 659*e107e82eSAnatoly Burakov n_tx_queue = nb_lcores; 660*e107e82eSAnatoly Burakov if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) 661*e107e82eSAnatoly Burakov n_tx_queue = MAX_TX_QUEUE_PER_PORT; 662*e107e82eSAnatoly Burakov ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, 663*e107e82eSAnatoly Burakov &port_conf); 664*e107e82eSAnatoly Burakov if (ret < 0) 665*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "Cannot configure device: " 666*e107e82eSAnatoly Burakov "err=%d, port=%d\n", 667*e107e82eSAnatoly Burakov ret, portid); 668*e107e82eSAnatoly Burakov 669*e107e82eSAnatoly Burakov rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 670*e107e82eSAnatoly Burakov print_ethaddr(" Address:", &ports_eth_addr[portid]); 671*e107e82eSAnatoly Burakov printf(", "); 672*e107e82eSAnatoly Burakov 673*e107e82eSAnatoly Burakov /* init one RX queue */ 674*e107e82eSAnatoly Burakov queueid = 0; 675*e107e82eSAnatoly Burakov printf("rxq=%d ", queueid); 676*e107e82eSAnatoly Burakov fflush(stdout); 677*e107e82eSAnatoly Burakov ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, 678*e107e82eSAnatoly Burakov rte_eth_dev_socket_id(portid), &rx_conf, 679*e107e82eSAnatoly Burakov pool_direct); 680*e107e82eSAnatoly Burakov if (ret < 0) 681*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: " 682*e107e82eSAnatoly Burakov "err=%d, port=%d\n", 683*e107e82eSAnatoly Burakov ret, portid); 684*e107e82eSAnatoly Burakov 685*e107e82eSAnatoly Burakov /* init one TX queue per couple (lcore,port) */ 686*e107e82eSAnatoly Burakov queueid = 0; 687*e107e82eSAnatoly Burakov for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 688*e107e82eSAnatoly Burakov if (rte_lcore_is_enabled(lcore_id) == 0) 689*e107e82eSAnatoly Burakov continue; 690*e107e82eSAnatoly Burakov printf("txq=%u,%d ", lcore_id, queueid); 691*e107e82eSAnatoly Burakov fflush(stdout); 692*e107e82eSAnatoly Burakov ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 693*e107e82eSAnatoly Burakov rte_eth_dev_socket_id(portid), &tx_conf); 694*e107e82eSAnatoly Burakov if (ret < 0) 695*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: " 696*e107e82eSAnatoly Burakov "err=%d, port=%d\n", ret, portid); 697*e107e82eSAnatoly Burakov 698*e107e82eSAnatoly Burakov qconf = &lcore_queue_conf[lcore_id]; 699*e107e82eSAnatoly Burakov qconf->tx_queue_id[portid] = queueid; 700*e107e82eSAnatoly Burakov queueid++; 701*e107e82eSAnatoly Burakov } 702*e107e82eSAnatoly Burakov 703*e107e82eSAnatoly Burakov /* Start device */ 704*e107e82eSAnatoly Burakov ret = rte_eth_dev_start(portid); 705*e107e82eSAnatoly Burakov if (ret < 0) 706*e107e82eSAnatoly Burakov rte_exit(EXIT_FAILURE, "rte_eth_dev_start: " 707*e107e82eSAnatoly Burakov "err=%d, port=%d\n", 708*e107e82eSAnatoly Burakov ret, portid); 709*e107e82eSAnatoly Burakov 710*e107e82eSAnatoly Burakov printf("done: "); 711*e107e82eSAnatoly Burakov 712*e107e82eSAnatoly Burakov /* Set port in promiscuous mode */ 713*e107e82eSAnatoly Burakov rte_eth_promiscuous_enable(portid); 714*e107e82eSAnatoly Burakov } 715*e107e82eSAnatoly Burakov 716*e107e82eSAnatoly Burakov check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); 717*e107e82eSAnatoly Burakov 718*e107e82eSAnatoly Burakov /* create the LPM table */ 719*e107e82eSAnatoly Burakov l3fwd_lpm = rte_lpm_create("L3FWD_LPM", rte_socket_id(), L3FWD_LPM_MAX_RULES, 0); 720*e107e82eSAnatoly Burakov if (l3fwd_lpm == NULL) 721*e107e82eSAnatoly Burakov rte_panic("Unable to create the l3fwd LPM table\n"); 722*e107e82eSAnatoly Burakov 723*e107e82eSAnatoly Burakov /* populate the LPM table */ 724*e107e82eSAnatoly Burakov for (i = 0; i < L3FWD_NUM_ROUTES; i++) { 725*e107e82eSAnatoly Burakov ret = rte_lpm_add(l3fwd_lpm, 726*e107e82eSAnatoly Burakov l3fwd_route_array[i].ip, 727*e107e82eSAnatoly Burakov l3fwd_route_array[i].depth, 728*e107e82eSAnatoly Burakov l3fwd_route_array[i].if_out); 729*e107e82eSAnatoly Burakov 730*e107e82eSAnatoly Burakov if (ret < 0) { 731*e107e82eSAnatoly Burakov rte_panic("Unable to add entry %u to the l3fwd " 732*e107e82eSAnatoly Burakov "LPM table\n", i); 733*e107e82eSAnatoly Burakov } 734*e107e82eSAnatoly Burakov 735*e107e82eSAnatoly Burakov printf("Adding route 0x%08x / %d (%d)\n", 736*e107e82eSAnatoly Burakov (unsigned) l3fwd_route_array[i].ip, 737*e107e82eSAnatoly Burakov l3fwd_route_array[i].depth, 738*e107e82eSAnatoly Burakov l3fwd_route_array[i].if_out); 739*e107e82eSAnatoly Burakov } 740*e107e82eSAnatoly Burakov 741*e107e82eSAnatoly Burakov /* launch per-lcore init on every lcore */ 742*e107e82eSAnatoly Burakov rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); 743*e107e82eSAnatoly Burakov RTE_LCORE_FOREACH_SLAVE(lcore_id) { 744*e107e82eSAnatoly Burakov if (rte_eal_wait_lcore(lcore_id) < 0) 745*e107e82eSAnatoly Burakov return -1; 746*e107e82eSAnatoly Burakov } 747*e107e82eSAnatoly Burakov 748*e107e82eSAnatoly Burakov return 0; 749*e107e82eSAnatoly Burakov } 750