1*76404edcSAsim Jamshed /* for io_module_func def'ns */ 2*76404edcSAsim Jamshed #include "io_module.h" 3*76404edcSAsim Jamshed /* for mtcp related def'ns */ 4*76404edcSAsim Jamshed #include "mtcp.h" 5*76404edcSAsim Jamshed /* for errno */ 6*76404edcSAsim Jamshed #include <errno.h> 7*76404edcSAsim Jamshed /* for logging */ 8*76404edcSAsim Jamshed #include "debug.h" 9*76404edcSAsim Jamshed /* for num_devices_* */ 10*76404edcSAsim Jamshed #include "config.h" 11*76404edcSAsim Jamshed /* for rte_max_eth_ports */ 12*76404edcSAsim Jamshed #include <rte_common.h> 13*76404edcSAsim Jamshed /* for rte_eth_rxconf */ 14*76404edcSAsim Jamshed #include <rte_ethdev.h> 15*76404edcSAsim Jamshed /* for delay funcs */ 16*76404edcSAsim Jamshed #include <rte_cycles.h> 17*76404edcSAsim Jamshed /* for ip pesudo-chksum */ 18*76404edcSAsim Jamshed #include <rte_ip.h> 19*76404edcSAsim Jamshed #define ENABLE_STATS_IOCTL 1 20*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 21*76404edcSAsim Jamshed /* for close */ 22*76404edcSAsim Jamshed #include <unistd.h> 23*76404edcSAsim Jamshed /* for open */ 24*76404edcSAsim Jamshed #include <fcntl.h> 25*76404edcSAsim Jamshed /* for ioctl */ 26*76404edcSAsim Jamshed #include <sys/ioctl.h> 27*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 28*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 29*76404edcSAsim Jamshed /* Essential macros */ 30*76404edcSAsim Jamshed #define MAX_RX_QUEUE_PER_LCORE MAX_CPUS 31*76404edcSAsim Jamshed #define MAX_TX_QUEUE_PER_PORT MAX_CPUS 32*76404edcSAsim Jamshed 33*76404edcSAsim Jamshed #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 34*76404edcSAsim Jamshed #define NB_MBUF 8192 35*76404edcSAsim Jamshed #define MEMPOOL_CACHE_SIZE 256 36*76404edcSAsim Jamshed 37*76404edcSAsim Jamshed /* 38*76404edcSAsim Jamshed * RX and TX Prefetch, Host, and Write-back threshold values should be 39*76404edcSAsim Jamshed * carefully set for optimal performance. Consult the network 40*76404edcSAsim Jamshed * controller's datasheet and supporting DPDK documentation for guidance 41*76404edcSAsim Jamshed * on how these parameters should be set. 42*76404edcSAsim Jamshed */ 43*76404edcSAsim Jamshed #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ 44*76404edcSAsim Jamshed #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ 45*76404edcSAsim Jamshed #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ 46*76404edcSAsim Jamshed 47*76404edcSAsim Jamshed /* 48*76404edcSAsim Jamshed * These default values are optimized for use with the Intel(R) 82599 10 GbE 49*76404edcSAsim Jamshed * Controller and the DPDK ixgbe PMD. Consider using other values for other 50*76404edcSAsim Jamshed * network controllers and/or network drivers. 51*76404edcSAsim Jamshed */ 52*76404edcSAsim Jamshed #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ 53*76404edcSAsim Jamshed #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ 54*76404edcSAsim Jamshed #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ 55*76404edcSAsim Jamshed 56*76404edcSAsim Jamshed #define MAX_PKT_BURST /*32*/64/*128*//*32*/ 57*76404edcSAsim Jamshed 58*76404edcSAsim Jamshed /* 59*76404edcSAsim Jamshed * Configurable number of RX/TX ring descriptors 60*76404edcSAsim Jamshed */ 61*76404edcSAsim Jamshed #define RTE_TEST_RX_DESC_DEFAULT 128 62*76404edcSAsim Jamshed #define RTE_TEST_TX_DESC_DEFAULT 512 63*76404edcSAsim Jamshed 64*76404edcSAsim Jamshed static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 65*76404edcSAsim Jamshed static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 66*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 67*76404edcSAsim Jamshed /* packet memory pools for storing packet bufs */ 68*76404edcSAsim Jamshed static struct rte_mempool *pktmbuf_pool[MAX_CPUS] = {NULL}; 69*76404edcSAsim Jamshed static uint8_t cpu_qid_map[RTE_MAX_ETHPORTS][MAX_CPUS] = {{0}}; 70*76404edcSAsim Jamshed 71*76404edcSAsim Jamshed //#define DEBUG 1 72*76404edcSAsim Jamshed #ifdef DEBUG 73*76404edcSAsim Jamshed /* ethernet addresses of ports */ 74*76404edcSAsim Jamshed static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 75*76404edcSAsim Jamshed #endif 76*76404edcSAsim Jamshed 77*76404edcSAsim Jamshed static struct rte_eth_conf port_conf = { 78*76404edcSAsim Jamshed .rxmode = { 79*76404edcSAsim Jamshed .mq_mode = ETH_MQ_RX_RSS, 80*76404edcSAsim Jamshed .max_rx_pkt_len = ETHER_MAX_LEN, 81*76404edcSAsim Jamshed .split_hdr_size = 0, 82*76404edcSAsim Jamshed .header_split = 0, /**< Header Split disabled */ 83*76404edcSAsim Jamshed .hw_ip_checksum = 1, /**< IP checksum offload enabled */ 84*76404edcSAsim Jamshed .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 85*76404edcSAsim Jamshed .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 86*76404edcSAsim Jamshed .hw_strip_crc = 1, /**< CRC stripped by hardware */ 87*76404edcSAsim Jamshed }, 88*76404edcSAsim Jamshed .rx_adv_conf = { 89*76404edcSAsim Jamshed .rss_conf = { 90*76404edcSAsim Jamshed .rss_key = NULL, 91*76404edcSAsim Jamshed .rss_hf = ETH_RSS_TCP 92*76404edcSAsim Jamshed }, 93*76404edcSAsim Jamshed }, 94*76404edcSAsim Jamshed .txmode = { 95*76404edcSAsim Jamshed .mq_mode = ETH_MQ_TX_NONE, 96*76404edcSAsim Jamshed }, 97*76404edcSAsim Jamshed #if 0 98*76404edcSAsim Jamshed .fdir_conf = { 99*76404edcSAsim Jamshed .mode = RTE_FDIR_MODE_PERFECT, 100*76404edcSAsim Jamshed .pballoc = RTE_FDIR_PBALLOC_256K, 101*76404edcSAsim Jamshed .status = RTE_FDIR_REPORT_STATUS_ALWAYS, 102*76404edcSAsim Jamshed //.flexbytes_offset = 0x6, 103*76404edcSAsim Jamshed .drop_queue = 127, 104*76404edcSAsim Jamshed }, 105*76404edcSAsim Jamshed #endif 106*76404edcSAsim Jamshed }; 107*76404edcSAsim Jamshed 108*76404edcSAsim Jamshed static const struct rte_eth_rxconf rx_conf = { 109*76404edcSAsim Jamshed .rx_thresh = { 110*76404edcSAsim Jamshed .pthresh = RX_PTHRESH, /* RX prefetch threshold reg */ 111*76404edcSAsim Jamshed .hthresh = RX_HTHRESH, /* RX host threshold reg */ 112*76404edcSAsim Jamshed .wthresh = RX_WTHRESH, /* RX write-back threshold reg */ 113*76404edcSAsim Jamshed }, 114*76404edcSAsim Jamshed .rx_free_thresh = 32, 115*76404edcSAsim Jamshed }; 116*76404edcSAsim Jamshed 117*76404edcSAsim Jamshed static const struct rte_eth_txconf tx_conf = { 118*76404edcSAsim Jamshed .tx_thresh = { 119*76404edcSAsim Jamshed .pthresh = TX_PTHRESH, /* TX prefetch threshold reg */ 120*76404edcSAsim Jamshed .hthresh = TX_HTHRESH, /* TX host threshold reg */ 121*76404edcSAsim Jamshed .wthresh = TX_WTHRESH, /* TX write-back threshold reg */ 122*76404edcSAsim Jamshed }, 123*76404edcSAsim Jamshed .tx_free_thresh = 0, /* Use PMD default values */ 124*76404edcSAsim Jamshed .tx_rs_thresh = 0, /* Use PMD default values */ 125*76404edcSAsim Jamshed /* 126*76404edcSAsim Jamshed * As the example won't handle mult-segments and offload cases, 127*76404edcSAsim Jamshed * set the flag by default. 128*76404edcSAsim Jamshed */ 129*76404edcSAsim Jamshed .txq_flags = 0x0, 130*76404edcSAsim Jamshed }; 131*76404edcSAsim Jamshed 132*76404edcSAsim Jamshed struct mbuf_table { 133*76404edcSAsim Jamshed unsigned len; /* length of queued packets */ 134*76404edcSAsim Jamshed struct rte_mbuf *m_table[MAX_PKT_BURST]; 135*76404edcSAsim Jamshed }; 136*76404edcSAsim Jamshed 137*76404edcSAsim Jamshed struct dpdk_private_context { 138*76404edcSAsim Jamshed struct mbuf_table rmbufs[RTE_MAX_ETHPORTS]; 139*76404edcSAsim Jamshed struct mbuf_table wmbufs[RTE_MAX_ETHPORTS]; 140*76404edcSAsim Jamshed struct rte_mempool *pktmbuf_pool; 141*76404edcSAsim Jamshed struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 142*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 143*76404edcSAsim Jamshed int fd; 144*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 145*76404edcSAsim Jamshed } __rte_cache_aligned; 146*76404edcSAsim Jamshed 147*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 148*76404edcSAsim Jamshed /** 149*76404edcSAsim Jamshed * stats struct passed on from user space to the driver 150*76404edcSAsim Jamshed */ 151*76404edcSAsim Jamshed struct stats_struct { 152*76404edcSAsim Jamshed uint64_t tx_bytes; 153*76404edcSAsim Jamshed uint64_t tx_pkts; 154*76404edcSAsim Jamshed uint64_t rx_bytes; 155*76404edcSAsim Jamshed uint64_t rx_pkts; 156*76404edcSAsim Jamshed uint8_t qid; 157*76404edcSAsim Jamshed uint8_t dev; 158*76404edcSAsim Jamshed }; 159*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 160*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 161*76404edcSAsim Jamshed void 162*76404edcSAsim Jamshed dpdk_init_handle(struct mtcp_thread_context *ctxt) 163*76404edcSAsim Jamshed { 164*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 165*76404edcSAsim Jamshed int i, j; 166*76404edcSAsim Jamshed char mempool_name[20]; 167*76404edcSAsim Jamshed 168*76404edcSAsim Jamshed /* create and initialize private I/O module context */ 169*76404edcSAsim Jamshed ctxt->io_private_context = calloc(1, sizeof(struct dpdk_private_context)); 170*76404edcSAsim Jamshed if (ctxt->io_private_context == NULL) { 171*76404edcSAsim Jamshed TRACE_ERROR("Failed to initialize ctxt->io_private_context: " 172*76404edcSAsim Jamshed "Can't allocate memory\n"); 173*76404edcSAsim Jamshed exit(EXIT_FAILURE); 174*76404edcSAsim Jamshed } 175*76404edcSAsim Jamshed 176*76404edcSAsim Jamshed sprintf(mempool_name, "mbuf_pool-%d", ctxt->cpu); 177*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *)ctxt->io_private_context; 178*76404edcSAsim Jamshed dpc->pktmbuf_pool = pktmbuf_pool[ctxt->cpu]; 179*76404edcSAsim Jamshed 180*76404edcSAsim Jamshed /* set wmbufs correctly */ 181*76404edcSAsim Jamshed for (j = 0; j < g_config.mos->netdev_table->num; j++) { 182*76404edcSAsim Jamshed /* Allocate wmbufs for each registered port */ 183*76404edcSAsim Jamshed for (i = 0; i < MAX_PKT_BURST; i++) { 184*76404edcSAsim Jamshed dpc->wmbufs[j].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]); 185*76404edcSAsim Jamshed if (dpc->wmbufs[j].m_table[i] == NULL) { 186*76404edcSAsim Jamshed TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n", 187*76404edcSAsim Jamshed ctxt->cpu, i, j); 188*76404edcSAsim Jamshed exit(EXIT_FAILURE); 189*76404edcSAsim Jamshed } 190*76404edcSAsim Jamshed } 191*76404edcSAsim Jamshed /* set mbufs queue length to 0 to begin with */ 192*76404edcSAsim Jamshed dpc->wmbufs[j].len = 0; 193*76404edcSAsim Jamshed } 194*76404edcSAsim Jamshed 195*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 196*76404edcSAsim Jamshed dpc->fd = open("/dev/dpdk-iface", O_RDWR); 197*76404edcSAsim Jamshed if (dpc->fd == -1) { 198*76404edcSAsim Jamshed TRACE_ERROR("Can't open /dev/dpdk-iface for context->cpu: %d!\n", 199*76404edcSAsim Jamshed ctxt->cpu); 200*76404edcSAsim Jamshed exit(EXIT_FAILURE); 201*76404edcSAsim Jamshed } 202*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 203*76404edcSAsim Jamshed } 204*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 205*76404edcSAsim Jamshed int 206*76404edcSAsim Jamshed dpdk_send_pkts(struct mtcp_thread_context *ctxt, int nif) 207*76404edcSAsim Jamshed { 208*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 209*76404edcSAsim Jamshed mtcp_manager_t mtcp; 210*76404edcSAsim Jamshed int ret; 211*76404edcSAsim Jamshed int qid; 212*76404edcSAsim Jamshed 213*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *)ctxt->io_private_context; 214*76404edcSAsim Jamshed mtcp = ctxt->mtcp_manager; 215*76404edcSAsim Jamshed ret = 0; 216*76404edcSAsim Jamshed qid = cpu_qid_map[nif][ctxt->cpu]; 217*76404edcSAsim Jamshed 218*76404edcSAsim Jamshed /* if queue is unassigned, skip it.. */ 219*76404edcSAsim Jamshed if (unlikely(qid == 0xFF)) 220*76404edcSAsim Jamshed return 0; 221*76404edcSAsim Jamshed 222*76404edcSAsim Jamshed /* if there are packets in the queue... flush them out to the wire */ 223*76404edcSAsim Jamshed if (dpc->wmbufs[nif].len >/*= MAX_PKT_BURST*/ 0) { 224*76404edcSAsim Jamshed struct rte_mbuf **pkts; 225*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 226*76404edcSAsim Jamshed struct stats_struct ss; 227*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 228*76404edcSAsim Jamshed int cnt = dpc->wmbufs[nif].len; 229*76404edcSAsim Jamshed pkts = dpc->wmbufs[nif].m_table; 230*76404edcSAsim Jamshed #ifdef NETSTAT 231*76404edcSAsim Jamshed mtcp->nstat.tx_packets[nif] += cnt; 232*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 233*76404edcSAsim Jamshed ss.tx_pkts = mtcp->nstat.tx_packets[nif]; 234*76404edcSAsim Jamshed ss.tx_bytes = mtcp->nstat.tx_bytes[nif]; 235*76404edcSAsim Jamshed ss.rx_pkts = mtcp->nstat.rx_packets[nif]; 236*76404edcSAsim Jamshed ss.rx_bytes = mtcp->nstat.rx_bytes[nif]; 237*76404edcSAsim Jamshed ss.qid = ctxt->cpu; 238*76404edcSAsim Jamshed ss.dev = nif; 239*76404edcSAsim Jamshed ioctl(dpc->fd, 0, &ss); 240*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 241*76404edcSAsim Jamshed #endif 242*76404edcSAsim Jamshed do { 243*76404edcSAsim Jamshed /* tx cnt # of packets */ 244*76404edcSAsim Jamshed ret = rte_eth_tx_burst(nif, qid, 245*76404edcSAsim Jamshed pkts, cnt); 246*76404edcSAsim Jamshed pkts += ret; 247*76404edcSAsim Jamshed cnt -= ret; 248*76404edcSAsim Jamshed /* if not all pkts were sent... then repeat the cycle */ 249*76404edcSAsim Jamshed } while (cnt > 0); 250*76404edcSAsim Jamshed 251*76404edcSAsim Jamshed #ifndef SHARE_IO_BUFFER 252*76404edcSAsim Jamshed int i; 253*76404edcSAsim Jamshed /* time to allocate fresh mbufs for the queue */ 254*76404edcSAsim Jamshed for (i = 0; i < dpc->wmbufs[nif].len; i++) { 255*76404edcSAsim Jamshed dpc->wmbufs[nif].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]); 256*76404edcSAsim Jamshed /* error checking */ 257*76404edcSAsim Jamshed if (unlikely(dpc->wmbufs[nif].m_table[i] == NULL)) { 258*76404edcSAsim Jamshed TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n", 259*76404edcSAsim Jamshed ctxt->cpu, i, nif); 260*76404edcSAsim Jamshed exit(EXIT_FAILURE); 261*76404edcSAsim Jamshed } 262*76404edcSAsim Jamshed } 263*76404edcSAsim Jamshed #endif 264*76404edcSAsim Jamshed /* reset the len of mbufs var after flushing of packets */ 265*76404edcSAsim Jamshed dpc->wmbufs[nif].len = 0; 266*76404edcSAsim Jamshed } 267*76404edcSAsim Jamshed 268*76404edcSAsim Jamshed return ret; 269*76404edcSAsim Jamshed } 270*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 271*76404edcSAsim Jamshed uint8_t * 272*76404edcSAsim Jamshed dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize) 273*76404edcSAsim Jamshed { 274*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 275*76404edcSAsim Jamshed mtcp_manager_t mtcp; 276*76404edcSAsim Jamshed struct rte_mbuf *m; 277*76404edcSAsim Jamshed uint8_t *ptr; 278*76404edcSAsim Jamshed int len_of_mbuf; 279*76404edcSAsim Jamshed 280*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *) ctxt->io_private_context; 281*76404edcSAsim Jamshed mtcp = ctxt->mtcp_manager; 282*76404edcSAsim Jamshed 283*76404edcSAsim Jamshed /* sanity check */ 284*76404edcSAsim Jamshed if (unlikely(dpc->wmbufs[nif].len == MAX_PKT_BURST)) 285*76404edcSAsim Jamshed return NULL; 286*76404edcSAsim Jamshed 287*76404edcSAsim Jamshed len_of_mbuf = dpc->wmbufs[nif].len; 288*76404edcSAsim Jamshed m = dpc->wmbufs[nif].m_table[len_of_mbuf]; 289*76404edcSAsim Jamshed 290*76404edcSAsim Jamshed /* retrieve the right write offset */ 291*76404edcSAsim Jamshed ptr = (void *)rte_pktmbuf_mtod(m, struct ether_hdr *); 292*76404edcSAsim Jamshed m->pkt_len = m->data_len = pktsize; 293*76404edcSAsim Jamshed m->nb_segs = 1; 294*76404edcSAsim Jamshed m->next = NULL; 295*76404edcSAsim Jamshed 296*76404edcSAsim Jamshed #ifdef NETSTAT 297*76404edcSAsim Jamshed mtcp->nstat.tx_bytes[nif] += pktsize + 24; 298*76404edcSAsim Jamshed #endif 299*76404edcSAsim Jamshed 300*76404edcSAsim Jamshed /* increment the len_of_mbuf var */ 301*76404edcSAsim Jamshed dpc->wmbufs[nif].len = len_of_mbuf + 1; 302*76404edcSAsim Jamshed 303*76404edcSAsim Jamshed return (uint8_t *)ptr; 304*76404edcSAsim Jamshed } 305*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 306*76404edcSAsim Jamshed void 307*76404edcSAsim Jamshed dpdk_set_wptr(struct mtcp_thread_context *ctxt, int out_nif, int in_nif, int index) 308*76404edcSAsim Jamshed { 309*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 310*76404edcSAsim Jamshed mtcp_manager_t mtcp; 311*76404edcSAsim Jamshed int len_of_mbuf; 312*76404edcSAsim Jamshed 313*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *) ctxt->io_private_context; 314*76404edcSAsim Jamshed mtcp = ctxt->mtcp_manager; 315*76404edcSAsim Jamshed 316*76404edcSAsim Jamshed /* sanity check */ 317*76404edcSAsim Jamshed if (unlikely(dpc->wmbufs[out_nif].len == MAX_PKT_BURST)) 318*76404edcSAsim Jamshed return; 319*76404edcSAsim Jamshed 320*76404edcSAsim Jamshed len_of_mbuf = dpc->wmbufs[out_nif].len; 321*76404edcSAsim Jamshed dpc->wmbufs[out_nif].m_table[len_of_mbuf] = 322*76404edcSAsim Jamshed dpc->rmbufs[in_nif].m_table[index]; 323*76404edcSAsim Jamshed 324*76404edcSAsim Jamshed dpc->wmbufs[out_nif].m_table[len_of_mbuf]->udata64 = 0; 325*76404edcSAsim Jamshed 326*76404edcSAsim Jamshed #ifdef NETSTAT 327*76404edcSAsim Jamshed mtcp->nstat.tx_bytes[out_nif] += dpc->rmbufs[in_nif].m_table[index]->pkt_len + 24; 328*76404edcSAsim Jamshed #endif 329*76404edcSAsim Jamshed 330*76404edcSAsim Jamshed /* increment the len_of_mbuf var */ 331*76404edcSAsim Jamshed dpc->wmbufs[out_nif].len = len_of_mbuf + 1; 332*76404edcSAsim Jamshed 333*76404edcSAsim Jamshed return; 334*76404edcSAsim Jamshed } 335*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 336*76404edcSAsim Jamshed static inline void 337*76404edcSAsim Jamshed free_pkts(struct rte_mbuf **mtable, unsigned len) 338*76404edcSAsim Jamshed { 339*76404edcSAsim Jamshed int i; 340*76404edcSAsim Jamshed 341*76404edcSAsim Jamshed /* free the freaking packets */ 342*76404edcSAsim Jamshed for (i = 0; i < len; i++) { 343*76404edcSAsim Jamshed if (mtable[i]->udata64 == 1) { 344*76404edcSAsim Jamshed rte_pktmbuf_free_seg(mtable[i]); 345*76404edcSAsim Jamshed RTE_MBUF_PREFETCH_TO_FREE(mtable[i+1]); 346*76404edcSAsim Jamshed } 347*76404edcSAsim Jamshed } 348*76404edcSAsim Jamshed } 349*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 350*76404edcSAsim Jamshed int32_t 351*76404edcSAsim Jamshed dpdk_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx) 352*76404edcSAsim Jamshed { 353*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 354*76404edcSAsim Jamshed int ret; 355*76404edcSAsim Jamshed uint8_t qid; 356*76404edcSAsim Jamshed 357*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *) ctxt->io_private_context; 358*76404edcSAsim Jamshed qid = cpu_qid_map[ifidx][ctxt->cpu]; 359*76404edcSAsim Jamshed 360*76404edcSAsim Jamshed /* if queue is unassigned, skip it.. */ 361*76404edcSAsim Jamshed if (qid == 0xFF) 362*76404edcSAsim Jamshed return 0; 363*76404edcSAsim Jamshed 364*76404edcSAsim Jamshed if (dpc->rmbufs[ifidx].len != 0) { 365*76404edcSAsim Jamshed free_pkts(dpc->rmbufs[ifidx].m_table, dpc->rmbufs[ifidx].len); 366*76404edcSAsim Jamshed dpc->rmbufs[ifidx].len = 0; 367*76404edcSAsim Jamshed } 368*76404edcSAsim Jamshed 369*76404edcSAsim Jamshed ret = rte_eth_rx_burst((uint8_t)ifidx, qid, 370*76404edcSAsim Jamshed dpc->pkts_burst, MAX_PKT_BURST); 371*76404edcSAsim Jamshed 372*76404edcSAsim Jamshed dpc->rmbufs[ifidx].len = ret; 373*76404edcSAsim Jamshed 374*76404edcSAsim Jamshed return ret; 375*76404edcSAsim Jamshed } 376*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 377*76404edcSAsim Jamshed uint8_t * 378*76404edcSAsim Jamshed dpdk_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len) 379*76404edcSAsim Jamshed { 380*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 381*76404edcSAsim Jamshed struct rte_mbuf *m; 382*76404edcSAsim Jamshed uint8_t *pktbuf; 383*76404edcSAsim Jamshed 384*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *) ctxt->io_private_context; 385*76404edcSAsim Jamshed 386*76404edcSAsim Jamshed 387*76404edcSAsim Jamshed m = dpc->pkts_burst[index]; 388*76404edcSAsim Jamshed /* tag to check if the packet is a local or a forwarded pkt */ 389*76404edcSAsim Jamshed m->udata64 = 1; 390*76404edcSAsim Jamshed /* don't enable pre-fetching... performance goes down */ 391*76404edcSAsim Jamshed //rte_prefetch0(rte_pktmbuf_mtod(m, void *)); 392*76404edcSAsim Jamshed *len = m->pkt_len; 393*76404edcSAsim Jamshed pktbuf = rte_pktmbuf_mtod(m, uint8_t *); 394*76404edcSAsim Jamshed 395*76404edcSAsim Jamshed /* enqueue the pkt ptr in mbuf */ 396*76404edcSAsim Jamshed dpc->rmbufs[ifidx].m_table[index] = m; 397*76404edcSAsim Jamshed 398*76404edcSAsim Jamshed return pktbuf; 399*76404edcSAsim Jamshed } 400*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 401*76404edcSAsim Jamshed int 402*76404edcSAsim Jamshed dpdk_get_nif(struct ifreq *ifr) 403*76404edcSAsim Jamshed { 404*76404edcSAsim Jamshed int i; 405*76404edcSAsim Jamshed static int num_dev = -1; 406*76404edcSAsim Jamshed static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 407*76404edcSAsim Jamshed /* get mac addr entries of 'detected' dpdk ports */ 408*76404edcSAsim Jamshed if (num_dev < 0) { 409*76404edcSAsim Jamshed num_dev = rte_eth_dev_count(); 410*76404edcSAsim Jamshed for (i = 0; i < num_dev; i++) 411*76404edcSAsim Jamshed rte_eth_macaddr_get(i, &ports_eth_addr[i]); 412*76404edcSAsim Jamshed } 413*76404edcSAsim Jamshed 414*76404edcSAsim Jamshed for (i = 0; i < num_dev; i++) 415*76404edcSAsim Jamshed if (!memcmp(&ifr->ifr_addr.sa_data[0], &ports_eth_addr[i], ETH_ALEN)) 416*76404edcSAsim Jamshed return i; 417*76404edcSAsim Jamshed 418*76404edcSAsim Jamshed return -1; 419*76404edcSAsim Jamshed } 420*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 421*76404edcSAsim Jamshed void 422*76404edcSAsim Jamshed dpdk_destroy_handle(struct mtcp_thread_context *ctxt) 423*76404edcSAsim Jamshed { 424*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 425*76404edcSAsim Jamshed int i; 426*76404edcSAsim Jamshed 427*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *) ctxt->io_private_context; 428*76404edcSAsim Jamshed 429*76404edcSAsim Jamshed /* free wmbufs */ 430*76404edcSAsim Jamshed for (i = 0; i < g_config.mos->netdev_table->num; i++) 431*76404edcSAsim Jamshed free_pkts(dpc->wmbufs[i].m_table, MAX_PKT_BURST); 432*76404edcSAsim Jamshed 433*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL 434*76404edcSAsim Jamshed /* free fd */ 435*76404edcSAsim Jamshed close(dpc->fd); 436*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */ 437*76404edcSAsim Jamshed 438*76404edcSAsim Jamshed /* free it all up */ 439*76404edcSAsim Jamshed free(dpc); 440*76404edcSAsim Jamshed } 441*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 442*76404edcSAsim Jamshed static void 443*76404edcSAsim Jamshed check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 444*76404edcSAsim Jamshed { 445*76404edcSAsim Jamshed #define CHECK_INTERVAL 100 /* 100ms */ 446*76404edcSAsim Jamshed #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 447*76404edcSAsim Jamshed 448*76404edcSAsim Jamshed uint8_t portid, count, all_ports_up, print_flag = 0; 449*76404edcSAsim Jamshed struct rte_eth_link link; 450*76404edcSAsim Jamshed 451*76404edcSAsim Jamshed printf("\nChecking link status"); 452*76404edcSAsim Jamshed fflush(stdout); 453*76404edcSAsim Jamshed for (count = 0; count <= MAX_CHECK_TIME; count++) { 454*76404edcSAsim Jamshed all_ports_up = 1; 455*76404edcSAsim Jamshed for (portid = 0; portid < port_num; portid++) { 456*76404edcSAsim Jamshed if ((port_mask & (1 << portid)) == 0) 457*76404edcSAsim Jamshed continue; 458*76404edcSAsim Jamshed memset(&link, 0, sizeof(link)); 459*76404edcSAsim Jamshed rte_eth_link_get_nowait(portid, &link); 460*76404edcSAsim Jamshed /* print link status if flag set */ 461*76404edcSAsim Jamshed if (print_flag == 1) { 462*76404edcSAsim Jamshed if (link.link_status) 463*76404edcSAsim Jamshed printf("Port %d Link Up - speed %u " 464*76404edcSAsim Jamshed "Mbps - %s\n", (uint8_t)portid, 465*76404edcSAsim Jamshed (unsigned)link.link_speed, 466*76404edcSAsim Jamshed (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 467*76404edcSAsim Jamshed ("full-duplex") : ("half-duplex\n")); 468*76404edcSAsim Jamshed else 469*76404edcSAsim Jamshed printf("Port %d Link Down\n", 470*76404edcSAsim Jamshed (uint8_t)portid); 471*76404edcSAsim Jamshed continue; 472*76404edcSAsim Jamshed } 473*76404edcSAsim Jamshed /* clear all_ports_up flag if any link down */ 474*76404edcSAsim Jamshed if (link.link_status == 0) { 475*76404edcSAsim Jamshed all_ports_up = 0; 476*76404edcSAsim Jamshed break; 477*76404edcSAsim Jamshed } 478*76404edcSAsim Jamshed } 479*76404edcSAsim Jamshed /* after finally printing all link status, get out */ 480*76404edcSAsim Jamshed if (print_flag == 1) 481*76404edcSAsim Jamshed break; 482*76404edcSAsim Jamshed 483*76404edcSAsim Jamshed if (all_ports_up == 0) { 484*76404edcSAsim Jamshed printf("."); 485*76404edcSAsim Jamshed fflush(stdout); 486*76404edcSAsim Jamshed rte_delay_ms(CHECK_INTERVAL); 487*76404edcSAsim Jamshed } 488*76404edcSAsim Jamshed 489*76404edcSAsim Jamshed /* set the print_flag if all ports up or timeout */ 490*76404edcSAsim Jamshed if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 491*76404edcSAsim Jamshed print_flag = 1; 492*76404edcSAsim Jamshed printf("done\n"); 493*76404edcSAsim Jamshed } 494*76404edcSAsim Jamshed } 495*76404edcSAsim Jamshed } 496*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 497*76404edcSAsim Jamshed #if 0 498*76404edcSAsim Jamshed static void 499*76404edcSAsim Jamshed dpdk_enable_fdir(int portid, uint8_t is_master) 500*76404edcSAsim Jamshed { 501*76404edcSAsim Jamshed struct rte_fdir_masks fdir_masks; 502*76404edcSAsim Jamshed struct rte_fdir_filter fdir_filter; 503*76404edcSAsim Jamshed int ret; 504*76404edcSAsim Jamshed 505*76404edcSAsim Jamshed memset(&fdir_filter, 0, sizeof(struct rte_fdir_filter)); 506*76404edcSAsim Jamshed fdir_filter.iptype = RTE_FDIR_IPTYPE_IPV4; 507*76404edcSAsim Jamshed fdir_filter.l4type = RTE_FDIR_L4TYPE_TCP; 508*76404edcSAsim Jamshed fdir_filter.ip_dst.ipv4_addr = g_config.mos->netdev_table->ent[portid]->ip_addr; 509*76404edcSAsim Jamshed 510*76404edcSAsim Jamshed if (is_master) { 511*76404edcSAsim Jamshed memset(&fdir_masks, 0, sizeof(struct rte_fdir_masks)); 512*76404edcSAsim Jamshed fdir_masks.src_ipv4_mask = 0x0; 513*76404edcSAsim Jamshed fdir_masks.dst_ipv4_mask = 0xFFFFFFFF; 514*76404edcSAsim Jamshed fdir_masks.src_port_mask = 0x0; 515*76404edcSAsim Jamshed fdir_masks.dst_port_mask = 0x0; 516*76404edcSAsim Jamshed 517*76404edcSAsim Jamshed /* 518*76404edcSAsim Jamshed * enable the following if the filter is IP-only 519*76404edcSAsim Jamshed * (non-TCP, non-UDP) 520*76404edcSAsim Jamshed */ 521*76404edcSAsim Jamshed /* fdir_masks.only_ip_flow = 1; */ 522*76404edcSAsim Jamshed rte_eth_dev_fdir_set_masks(portid, &fdir_masks); 523*76404edcSAsim Jamshed ret = rte_eth_dev_fdir_add_perfect_filter(portid, 524*76404edcSAsim Jamshed &fdir_filter, 525*76404edcSAsim Jamshed 0, 526*76404edcSAsim Jamshed g_config.mos->multiprocess_curr_core, 527*76404edcSAsim Jamshed 0); 528*76404edcSAsim Jamshed } else { 529*76404edcSAsim Jamshed ret = rte_eth_dev_fdir_update_perfect_filter(portid, 530*76404edcSAsim Jamshed &fdir_filter, 531*76404edcSAsim Jamshed 0, 532*76404edcSAsim Jamshed g_config.mos->multiprocess_curr_core, 533*76404edcSAsim Jamshed 0); 534*76404edcSAsim Jamshed } 535*76404edcSAsim Jamshed if (ret < 0) { 536*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, 537*76404edcSAsim Jamshed "fdir_add_perfect_filter_t call failed!: %d\n", 538*76404edcSAsim Jamshed ret); 539*76404edcSAsim Jamshed } 540*76404edcSAsim Jamshed fprintf(stderr, "Filter for device ifidx: %d added\n", portid); 541*76404edcSAsim Jamshed } 542*76404edcSAsim Jamshed #endif 543*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 544*76404edcSAsim Jamshed int32_t 545*76404edcSAsim Jamshed dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp) 546*76404edcSAsim Jamshed { 547*76404edcSAsim Jamshed struct dpdk_private_context *dpc; 548*76404edcSAsim Jamshed struct rte_mbuf *m; 549*76404edcSAsim Jamshed int len_of_mbuf; 550*76404edcSAsim Jamshed struct iphdr *iph; 551*76404edcSAsim Jamshed struct tcphdr *tcph; 552*76404edcSAsim Jamshed RssInfo *rss_i; 553*76404edcSAsim Jamshed 554*76404edcSAsim Jamshed iph = (struct iphdr *)argp; 555*76404edcSAsim Jamshed dpc = (struct dpdk_private_context *)ctx->io_private_context; 556*76404edcSAsim Jamshed len_of_mbuf = dpc->wmbufs[nif].len; 557*76404edcSAsim Jamshed rss_i = NULL; 558*76404edcSAsim Jamshed 559*76404edcSAsim Jamshed switch (cmd) { 560*76404edcSAsim Jamshed case PKT_TX_IP_CSUM: 561*76404edcSAsim Jamshed m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1]; 562*76404edcSAsim Jamshed m->ol_flags = PKT_TX_OUTER_IP_CKSUM | 563*76404edcSAsim Jamshed PKT_TX_IP_CKSUM | PKT_TX_IPV4; 564*76404edcSAsim Jamshed m->l2_len = sizeof(struct ether_hdr); 565*76404edcSAsim Jamshed m->l3_len = (iph->ihl<<2); 566*76404edcSAsim Jamshed break; 567*76404edcSAsim Jamshed case PKT_TX_TCP_CSUM: 568*76404edcSAsim Jamshed m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1]; 569*76404edcSAsim Jamshed tcph = (struct tcphdr *)((unsigned char *)iph + (iph->ihl<<2)); 570*76404edcSAsim Jamshed m->ol_flags |= PKT_TX_TCP_CKSUM; 571*76404edcSAsim Jamshed tcph->check = rte_ipv4_phdr_cksum((struct ipv4_hdr *)iph, m->ol_flags); 572*76404edcSAsim Jamshed break; 573*76404edcSAsim Jamshed case PKT_RX_RSS: 574*76404edcSAsim Jamshed rss_i = (RssInfo *)argp; 575*76404edcSAsim Jamshed m = dpc->pkts_burst[rss_i->pktidx]; 576*76404edcSAsim Jamshed rss_i->hash_value = m->hash.rss; 577*76404edcSAsim Jamshed break; 578*76404edcSAsim Jamshed default: 579*76404edcSAsim Jamshed goto dev_ioctl_err; 580*76404edcSAsim Jamshed } 581*76404edcSAsim Jamshed 582*76404edcSAsim Jamshed return 0; 583*76404edcSAsim Jamshed dev_ioctl_err: 584*76404edcSAsim Jamshed return -1; 585*76404edcSAsim Jamshed } 586*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 587*76404edcSAsim Jamshed void 588*76404edcSAsim Jamshed dpdk_load_module_upper_half(void) 589*76404edcSAsim Jamshed { 590*76404edcSAsim Jamshed int cpu = g_config.mos->num_cores, ret; 591*76404edcSAsim Jamshed uint32_t cpumask = 0; 592*76404edcSAsim Jamshed char cpumaskbuf[10]; 593*76404edcSAsim Jamshed char mem_channels[5]; 594*76404edcSAsim Jamshed 595*76404edcSAsim Jamshed /* set the log level */ 596*76404edcSAsim Jamshed rte_set_log_type(RTE_LOGTYPE_PMD, 0); 597*76404edcSAsim Jamshed rte_set_log_type(RTE_LOGTYPE_MALLOC, 0); 598*76404edcSAsim Jamshed rte_set_log_type(RTE_LOGTYPE_MEMPOOL, 0); 599*76404edcSAsim Jamshed rte_set_log_type(RTE_LOGTYPE_RING, 0); 600*76404edcSAsim Jamshed rte_set_log_level(RTE_LOG_WARNING); 601*76404edcSAsim Jamshed 602*76404edcSAsim Jamshed /* get the cpu mask */ 603*76404edcSAsim Jamshed for (ret = 0; ret < cpu; ret++) 604*76404edcSAsim Jamshed cpumask = (cpumask | (1 << ret)); 605*76404edcSAsim Jamshed sprintf(cpumaskbuf, "%X", cpumask); 606*76404edcSAsim Jamshed 607*76404edcSAsim Jamshed /* get the mem channels per socket */ 608*76404edcSAsim Jamshed if (g_config.mos->nb_mem_channels == 0) { 609*76404edcSAsim Jamshed TRACE_ERROR("DPDK module requires # of memory channels " 610*76404edcSAsim Jamshed "per socket parameter!\n"); 611*76404edcSAsim Jamshed exit(EXIT_FAILURE); 612*76404edcSAsim Jamshed } 613*76404edcSAsim Jamshed sprintf(mem_channels, "%d", g_config.mos->nb_mem_channels); 614*76404edcSAsim Jamshed 615*76404edcSAsim Jamshed /* initialize the rte env first, what a waste of implementation effort! */ 616*76404edcSAsim Jamshed char *argv[] = {"", 617*76404edcSAsim Jamshed "-c", 618*76404edcSAsim Jamshed cpumaskbuf, 619*76404edcSAsim Jamshed "-n", 620*76404edcSAsim Jamshed mem_channels, 621*76404edcSAsim Jamshed "--proc-type=auto", 622*76404edcSAsim Jamshed "" 623*76404edcSAsim Jamshed }; 624*76404edcSAsim Jamshed const int argc = 6; 625*76404edcSAsim Jamshed 626*76404edcSAsim Jamshed /* 627*76404edcSAsim Jamshed * re-set getopt extern variable optind. 628*76404edcSAsim Jamshed * this issue was a bitch to debug 629*76404edcSAsim Jamshed * rte_eal_init() internally uses getopt() syscall 630*76404edcSAsim Jamshed * mtcp applications that also use an `external' getopt 631*76404edcSAsim Jamshed * will cause a violent crash if optind is not reset to zero 632*76404edcSAsim Jamshed * prior to calling the func below... 633*76404edcSAsim Jamshed * see man getopt(3) for more details 634*76404edcSAsim Jamshed */ 635*76404edcSAsim Jamshed optind = 0; 636*76404edcSAsim Jamshed 637*76404edcSAsim Jamshed /* initialize the dpdk eal env */ 638*76404edcSAsim Jamshed ret = rte_eal_init(argc, argv); 639*76404edcSAsim Jamshed if (ret < 0) 640*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Invalid EAL args!\n"); 641*76404edcSAsim Jamshed 642*76404edcSAsim Jamshed } 643*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 644*76404edcSAsim Jamshed void 645*76404edcSAsim Jamshed dpdk_load_module_lower_half(void) 646*76404edcSAsim Jamshed { 647*76404edcSAsim Jamshed int portid, rxlcore_id, ret; 648*76404edcSAsim Jamshed struct rte_eth_fc_conf fc_conf; /* for Ethernet flow control settings */ 649*76404edcSAsim Jamshed /* setting the rss key */ 650*76404edcSAsim Jamshed static const uint8_t key[] = { 651*76404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 652*76404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 653*76404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 654*76404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 655*76404edcSAsim Jamshed }; 656*76404edcSAsim Jamshed 657*76404edcSAsim Jamshed port_conf.rx_adv_conf.rss_conf.rss_key = (uint8_t *)&key; 658*76404edcSAsim Jamshed port_conf.rx_adv_conf.rss_conf.rss_key_len = sizeof(key); 659*76404edcSAsim Jamshed 660*76404edcSAsim Jamshed /* resetting cpu_qid mapping */ 661*76404edcSAsim Jamshed memset(cpu_qid_map, 0xFF, sizeof(cpu_qid_map)); 662*76404edcSAsim Jamshed 663*76404edcSAsim Jamshed if (!g_config.mos->multiprocess 664*76404edcSAsim Jamshed || (g_config.mos->multiprocess && g_config.mos->multiprocess_is_master)) { 665*76404edcSAsim Jamshed for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) { 666*76404edcSAsim Jamshed char name[20]; 667*76404edcSAsim Jamshed sprintf(name, "mbuf_pool-%d", rxlcore_id); 668*76404edcSAsim Jamshed /* create the mbuf pools */ 669*76404edcSAsim Jamshed pktmbuf_pool[rxlcore_id] = 670*76404edcSAsim Jamshed rte_mempool_create(name, NB_MBUF, 671*76404edcSAsim Jamshed MBUF_SIZE, MEMPOOL_CACHE_SIZE, 672*76404edcSAsim Jamshed sizeof(struct rte_pktmbuf_pool_private), 673*76404edcSAsim Jamshed rte_pktmbuf_pool_init, NULL, 674*76404edcSAsim Jamshed rte_pktmbuf_init, NULL, 675*76404edcSAsim Jamshed rte_lcore_to_socket_id(rxlcore_id), 0); 676*76404edcSAsim Jamshed if (pktmbuf_pool[rxlcore_id] == NULL) 677*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 678*76404edcSAsim Jamshed } 679*76404edcSAsim Jamshed 680*76404edcSAsim Jamshed /* Initialise each port */ 681*76404edcSAsim Jamshed for (portid = 0; portid < g_config.mos->netdev_table->num; portid++) { 682*76404edcSAsim Jamshed int num_queue = 0, eth_idx, i, queue_id; 683*76404edcSAsim Jamshed for (eth_idx = 0; eth_idx < g_config.mos->netdev_table->num; eth_idx++) 684*76404edcSAsim Jamshed if (portid == g_config.mos->netdev_table->ent[eth_idx]->ifindex) 685*76404edcSAsim Jamshed break; 686*76404edcSAsim Jamshed if (eth_idx == g_config.mos->netdev_table->num) 687*76404edcSAsim Jamshed continue; 688*76404edcSAsim Jamshed for (i = 0; i < sizeof(uint64_t) * 8; i++) 689*76404edcSAsim Jamshed if (g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << i)) 690*76404edcSAsim Jamshed num_queue++; 691*76404edcSAsim Jamshed 692*76404edcSAsim Jamshed /* set 'num_queues' (used for GetRSSCPUCore() in util.c) */ 693*76404edcSAsim Jamshed num_queues = num_queue; 694*76404edcSAsim Jamshed 695*76404edcSAsim Jamshed /* init port */ 696*76404edcSAsim Jamshed printf("Initializing port %u... ", (unsigned) portid); 697*76404edcSAsim Jamshed fflush(stdout); 698*76404edcSAsim Jamshed ret = rte_eth_dev_configure(portid, num_queue, num_queue, 699*76404edcSAsim Jamshed &port_conf); 700*76404edcSAsim Jamshed if (ret < 0) 701*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Cannot configure device:" 702*76404edcSAsim Jamshed "err=%d, port=%u\n", 703*76404edcSAsim Jamshed ret, (unsigned) portid); 704*76404edcSAsim Jamshed 705*76404edcSAsim Jamshed /* init one RX queue per CPU */ 706*76404edcSAsim Jamshed fflush(stdout); 707*76404edcSAsim Jamshed #ifdef DEBUG 708*76404edcSAsim Jamshed rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 709*76404edcSAsim Jamshed #endif 710*76404edcSAsim Jamshed queue_id = 0; 711*76404edcSAsim Jamshed for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) { 712*76404edcSAsim Jamshed if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id))) 713*76404edcSAsim Jamshed continue; 714*76404edcSAsim Jamshed ret = rte_eth_rx_queue_setup(portid, queue_id, nb_rxd, 715*76404edcSAsim Jamshed rte_eth_dev_socket_id(portid), &rx_conf, 716*76404edcSAsim Jamshed pktmbuf_pool[rxlcore_id]); 717*76404edcSAsim Jamshed if (ret < 0) 718*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:" 719*76404edcSAsim Jamshed "err=%d, port=%u, queueid: %d\n", 720*76404edcSAsim Jamshed ret, (unsigned) portid, rxlcore_id); 721*76404edcSAsim Jamshed cpu_qid_map[portid][rxlcore_id] = queue_id++; 722*76404edcSAsim Jamshed } 723*76404edcSAsim Jamshed 724*76404edcSAsim Jamshed /* init one TX queue on each port per CPU (this is redundant for 725*76404edcSAsim Jamshed * this app) */ 726*76404edcSAsim Jamshed fflush(stdout); 727*76404edcSAsim Jamshed queue_id = 0; 728*76404edcSAsim Jamshed for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) { 729*76404edcSAsim Jamshed if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id))) 730*76404edcSAsim Jamshed continue; 731*76404edcSAsim Jamshed ret = rte_eth_tx_queue_setup(portid, queue_id++, nb_txd, 732*76404edcSAsim Jamshed rte_eth_dev_socket_id(portid), &tx_conf); 733*76404edcSAsim Jamshed if (ret < 0) 734*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:" 735*76404edcSAsim Jamshed "err=%d, port=%u, queueid: %d\n", 736*76404edcSAsim Jamshed ret, (unsigned) portid, rxlcore_id); 737*76404edcSAsim Jamshed } 738*76404edcSAsim Jamshed 739*76404edcSAsim Jamshed /* Start device */ 740*76404edcSAsim Jamshed ret = rte_eth_dev_start(portid); 741*76404edcSAsim Jamshed if (ret < 0) 742*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", 743*76404edcSAsim Jamshed ret, (unsigned) portid); 744*76404edcSAsim Jamshed 745*76404edcSAsim Jamshed printf("done: \n"); 746*76404edcSAsim Jamshed rte_eth_promiscuous_enable(portid); 747*76404edcSAsim Jamshed 748*76404edcSAsim Jamshed /* retrieve current flow control settings per port */ 749*76404edcSAsim Jamshed memset(&fc_conf, 0, sizeof(fc_conf)); 750*76404edcSAsim Jamshed ret = rte_eth_dev_flow_ctrl_get(portid, &fc_conf); 751*76404edcSAsim Jamshed if (ret != 0) { 752*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Failed to get flow control info!\n"); 753*76404edcSAsim Jamshed } 754*76404edcSAsim Jamshed 755*76404edcSAsim Jamshed /* and just disable the rx/tx flow control */ 756*76404edcSAsim Jamshed fc_conf.mode = RTE_FC_NONE; 757*76404edcSAsim Jamshed ret = rte_eth_dev_flow_ctrl_set(portid, &fc_conf); 758*76404edcSAsim Jamshed if (ret != 0) { 759*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Failed to set flow control info!: errno: %d\n", 760*76404edcSAsim Jamshed ret); 761*76404edcSAsim Jamshed } 762*76404edcSAsim Jamshed 763*76404edcSAsim Jamshed #ifdef DEBUG 764*76404edcSAsim Jamshed printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", 765*76404edcSAsim Jamshed (unsigned) portid, 766*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[0], 767*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[1], 768*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[2], 769*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[3], 770*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[4], 771*76404edcSAsim Jamshed ports_eth_addr[portid].addr_bytes[5]); 772*76404edcSAsim Jamshed #endif 773*76404edcSAsim Jamshed #if 0 774*76404edcSAsim Jamshed /* if multi-process support is enabled, then turn on FDIR */ 775*76404edcSAsim Jamshed if (g_config.mos->multiprocess) 776*76404edcSAsim Jamshed dpdk_enable_fdir(portid, g_config.mos->multiprocess_is_master); 777*76404edcSAsim Jamshed #endif 778*76404edcSAsim Jamshed } 779*76404edcSAsim Jamshed } else { /* g_config.mos->multiprocess && !g_config.mos->multiprocess_is_master */ 780*76404edcSAsim Jamshed for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) { 781*76404edcSAsim Jamshed char name[20]; 782*76404edcSAsim Jamshed sprintf(name, "mbuf_pool-%d", rxlcore_id); 783*76404edcSAsim Jamshed /* initialize the mbuf pools */ 784*76404edcSAsim Jamshed pktmbuf_pool[rxlcore_id] = 785*76404edcSAsim Jamshed rte_mempool_lookup(name); 786*76404edcSAsim Jamshed if (pktmbuf_pool[rxlcore_id] == NULL) 787*76404edcSAsim Jamshed rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 788*76404edcSAsim Jamshed } 789*76404edcSAsim Jamshed #if 0 790*76404edcSAsim Jamshed for (portid = 0; portid < g_config.mos->netdev_table->num; portid++) 791*76404edcSAsim Jamshed dpdk_enable_fdir(portid, g_config.mos->multiprocess_is_master); 792*76404edcSAsim Jamshed #endif 793*76404edcSAsim Jamshed } 794*76404edcSAsim Jamshed 795*76404edcSAsim Jamshed check_all_ports_link_status(g_config.mos->netdev_table->num, 0xFFFFFFFF); 796*76404edcSAsim Jamshed } 797*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 798*76404edcSAsim Jamshed io_module_func dpdk_module_func = { 799*76404edcSAsim Jamshed .load_module_upper_half = dpdk_load_module_upper_half, 800*76404edcSAsim Jamshed .load_module_lower_half = dpdk_load_module_lower_half, 801*76404edcSAsim Jamshed .init_handle = dpdk_init_handle, 802*76404edcSAsim Jamshed .link_devices = NULL, 803*76404edcSAsim Jamshed .release_pkt = NULL, 804*76404edcSAsim Jamshed .send_pkts = dpdk_send_pkts, 805*76404edcSAsim Jamshed .get_wptr = dpdk_get_wptr, 806*76404edcSAsim Jamshed .recv_pkts = dpdk_recv_pkts, 807*76404edcSAsim Jamshed .get_rptr = dpdk_get_rptr, 808*76404edcSAsim Jamshed .get_nif = dpdk_get_nif, 809*76404edcSAsim Jamshed .select = NULL, 810*76404edcSAsim Jamshed .destroy_handle = dpdk_destroy_handle, 811*76404edcSAsim Jamshed .dev_ioctl = dpdk_dev_ioctl, 812*76404edcSAsim Jamshed .set_wptr = dpdk_set_wptr, 813*76404edcSAsim Jamshed }; 814*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 815*76404edcSAsim Jamshed 816