void wr_port_matrix_dump(l2p_t * l2p) { uint32_t pid, lid; uint8_t first, last; rxtx_t cnt; first = last = 0; printf("\n=== port to lcore mapping table (# lcores %d) ===\n", wr_lcore_mask(&first, &last)); printf(" lcore: "); for(lid = first; lid <= last; lid++) printf(" %2d ", lid); printf("\n"); for(pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { cnt.rxtx = wr_get_map(l2p, pid, RTE_MAX_LCORE); if ( cnt.rxtx == 0 ) continue; printf("port %2d:", pid); for(lid = first; lid <= last; lid++) { cnt.rxtx = wr_get_map(l2p, pid, lid); if ( lid == rte_get_master_lcore() ) printf(" %s:%s", " D", " T"); else printf(" %2d:%2d", cnt.rx, cnt.tx); } cnt.rxtx = wr_get_map(l2p, pid, RTE_MAX_LCORE); printf(" = %2d:%2d\n", cnt.rx, cnt.tx); } printf("Total :"); for(lid = first; lid <= last; lid++) { cnt.rxtx = wr_get_map(l2p, RTE_MAX_ETHPORTS, lid); printf(" %2d:%2d", cnt.rx, cnt.tx); } printf("\n Display and Timer on lcore %d, rx:tx counts per port/lcore\n\n", rte_get_master_lcore()); fflush(stdout); }
void pktgen_config_ports(void) { uint32_t lid, pid, i, s, q, sid; rxtx_t rt; pkt_seq_t * pkt; port_info_t * info; char buff[RTE_MEMZONE_NAMESIZE]; int32_t ret, cache_size; char output_buff[256] = { 0 }; // Find out the total number of ports in the system. // We have already blacklisted the ones we needed to in main routine. pktgen.nb_ports = rte_eth_dev_count(); if (pktgen.nb_ports > RTE_MAX_ETHPORTS) pktgen.nb_ports = RTE_MAX_ETHPORTS; if ( pktgen.nb_ports == 0 ) pktgen_log_panic("*** Did not find any ports to use ***"); pktgen.starting_port = 0; // Setup the number of ports to display at a time if ( pktgen.nb_ports > pktgen.nb_ports_per_page ) pktgen.ending_port = pktgen.starting_port + pktgen.nb_ports_per_page; else pktgen.ending_port = pktgen.starting_port + pktgen.nb_ports; wr_port_matrix_dump(pktgen.l2p); pktgen_log_info("Configuring %d ports, MBUF Size %d, MBUF Cache Size %d", pktgen.nb_ports, MBUF_SIZE, MBUF_CACHE_SIZE); // For each lcore setup each port that is handled by that lcore. for(lid = 0; lid < RTE_MAX_LCORE; lid++) { if ( wr_get_map(pktgen.l2p, RTE_MAX_ETHPORTS, lid) == 0 ) continue; // For each port attached or handled by the lcore for(pid = 0; pid < pktgen.nb_ports; pid++) { // If non-zero then this port is handled by this lcore. if ( wr_get_map(pktgen.l2p, pid, lid) == 0 ) continue; wr_set_port_private(pktgen.l2p, pid, &pktgen.info[pid]); pktgen.info[pid].pid = pid; } } wr_dump_l2p(pktgen.l2p); pktgen.total_mem_used = 0; for(pid = 0; pid < pktgen.nb_ports; pid++) { // Skip if we do not have any lcores attached to a port. if ( (rt.rxtx = wr_get_map(pktgen.l2p, pid, RTE_MAX_LCORE)) == 0 ) continue; pktgen.port_cnt++; snprintf(output_buff, sizeof(output_buff), "Initialize Port %d -- TxQ %d, RxQ %d", pid, rt.tx, rt.rx); info = wr_get_port_private(pktgen.l2p, pid); // Create the pkt header structures for transmitting sequence of packets. snprintf(buff, sizeof(buff), "seq_hdr_%d", pid); info->seq_pkt = (pkt_seq_t *)rte_zmalloc(buff, (sizeof(pkt_seq_t) * NUM_TOTAL_PKTS), RTE_CACHE_LINE_SIZE); if ( info->seq_pkt == NULL ) pktgen_log_panic("Unable to allocate %d pkt_seq_t headers", NUM_TOTAL_PKTS); info->seqIdx = 0; info->seqCnt = 0; info->nb_mbufs = MAX_MBUFS_PER_PORT; cache_size = (info->nb_mbufs > RTE_MEMPOOL_CACHE_MAX_SIZE)? RTE_MEMPOOL_CACHE_MAX_SIZE : info->nb_mbufs; pktgen_port_conf_setup(pid, &rt, &default_port_conf); if ( (ret = rte_eth_dev_configure(pid, rt.rx, rt.tx, &info->port_conf)) < 0) pktgen_log_panic("Cannot configure device: port=%d, Num queues %d,%d (%d)%s", pid, rt.rx, rt.tx, errno, rte_strerror(-ret)); pkt = &info->seq_pkt[SINGLE_PKT]; // Grab the source MAC addresses */ rte_eth_macaddr_get(pid, &pkt->eth_src_addr); pktgen_log_info("%s, Src MAC %02x:%02x:%02x:%02x:%02x:%02x", output_buff, pkt->eth_src_addr.addr_bytes[0], pkt->eth_src_addr.addr_bytes[1], pkt->eth_src_addr.addr_bytes[2], pkt->eth_src_addr.addr_bytes[3], pkt->eth_src_addr.addr_bytes[4], pkt->eth_src_addr.addr_bytes[5]); // Copy the first Src MAC address in SINGLE_PKT to the rest of the sequence packets. for (i = 0; i < NUM_SEQ_PKTS; i++) ethAddrCopy( &info->seq_pkt[i].eth_src_addr, &pkt->eth_src_addr ); pktgen.mem_used = 0; for(q = 0; q < rt.rx; q++) { // grab the socket id value based on the lcore being used. sid = rte_lcore_to_socket_id(wr_get_port_lid(pktgen.l2p, pid, q)); // Create and initialize the default Receive buffers. info->q[q].rx_mp = pktgen_mbuf_pool_create("Default RX", pid, q, info->nb_mbufs, sid, cache_size); if ( info->q[q].rx_mp == NULL ) pktgen_log_panic("Cannot init port %d for Default RX mbufs", pid); ret = rte_eth_rx_queue_setup(pid, q, pktgen.nb_rxd, sid, &info->rx_conf, pktgen.info[pid].q[q].rx_mp); if (ret < 0) pktgen_log_panic("rte_eth_rx_queue_setup: err=%d, port=%d, %s", ret, pid, rte_strerror(-ret)); } pktgen_log_info(""); for(q = 0; q < rt.tx; q++) { // grab the socket id value based on the lcore being used. sid = rte_lcore_to_socket_id(wr_get_port_lid(pktgen.l2p, pid, q)); // Create and initialize the default Transmit buffers. info->q[q].tx_mp = pktgen_mbuf_pool_create("Default TX", pid, q, MAX_MBUFS_PER_PORT, sid, cache_size); if ( info->q[q].tx_mp == NULL ) pktgen_log_panic("Cannot init port %d for Default TX mbufs", pid); // Create and initialize the range Transmit buffers. info->q[q].range_mp = pktgen_mbuf_pool_create("Range TX", pid, q, MAX_MBUFS_PER_PORT, sid, 0); if ( info->q[q].range_mp == NULL ) pktgen_log_panic("Cannot init port %d for Range TX mbufs", pid); // Create and initialize the sequence Transmit buffers. info->q[q].seq_mp = pktgen_mbuf_pool_create("Sequence TX", pid, q, MAX_MBUFS_PER_PORT, sid, cache_size); if ( info->q[q].seq_mp == NULL ) pktgen_log_panic("Cannot init port %d for Sequence TX mbufs", pid); // Used for sending special packets like ARP requests info->q[q].special_mp = pktgen_mbuf_pool_create("Special TX", pid, q, MAX_SPECIAL_MBUFS, sid, cache_size); if (info->q[q].special_mp == NULL) pktgen_log_panic("Cannot init port %d for Special TX mbufs", pid); // Setup the PCAP file for each port if ( pktgen.info[pid].pcap != NULL ) { if ( pktgen_pcap_parse(pktgen.info[pid].pcap, info, q) == -1 ) pktgen_log_panic("Cannot load PCAP file for port %d", pid); } // Find out the link speed to program the WTHRESH value correctly. pktgen_get_link_status(info, pid, 0); //info->tx_conf.tx_thresh.wthresh = (info->link.link_speed == 1000)? TX_WTHRESH_1GB : TX_WTHRESH; ret = rte_eth_tx_queue_setup(pid, q, pktgen.nb_txd, sid, &info->tx_conf); if (ret < 0) pktgen_log_panic("rte_eth_tx_queue_setup: err=%d, port=%d, %s", ret, pid, rte_strerror(-ret)); #if 0 ret = rte_eth_dev_flow_ctrl_set(pid, &fc_conf); if (ret < 0) pktgen_log_panic("rte_eth_dev_flow_ctrl_set: err=%d, port=%d, %s", ret, pid, rte_strerror(-ret)); #endif pktgen_log_info(""); } pktgen_log_info("%*sPort memory used = %6lu KB", 71, " ", (pktgen.mem_used + 1023)/1024); } pktgen_log_info("%*sTotal memory used = %6lu KB", 70, " ", (pktgen.total_mem_used + 1023)/1024); // Start up the ports and display the port Link status for(pid = 0; pid < pktgen.nb_ports; pid++) { if ( wr_get_map(pktgen.l2p, pid, RTE_MAX_LCORE) == 0 ) continue; info = wr_get_port_private(pktgen.l2p, pid); /* Start device */ if ( (ret = rte_eth_dev_start(pid)) < 0 ) pktgen_log_panic("rte_eth_dev_start: port=%d, %s", pid, rte_strerror(-ret)); pktgen_get_link_status(info, pid, 1); if (info->link.link_status) { snprintf(output_buff, sizeof(output_buff), "Port %2d: Link Up - speed %u Mbps - %s", pid, (uint32_t) info->link.link_speed, (info->link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); } else snprintf(output_buff, sizeof(output_buff), "Port %2d: Link Down", pid); // If enabled, put device in promiscuous mode. if (pktgen.flags & PROMISCUOUS_ON_FLAG) { strncatf(output_buff, " <Enable promiscuous mode>"); rte_eth_promiscuous_enable(pid); } pktgen_log_info("%s", output_buff); pktgen.info[pid].seq_pkt[SINGLE_PKT].pktSize = MIN_PKT_SIZE; // Setup the port and packet defaults. (must be after link speed is found) for (s = 0; s < NUM_TOTAL_PKTS; s++) pktgen_port_defaults(pid, s); pktgen_range_setup(info); pktgen_rnd_bits_init(&pktgen.info[pid].rnd_bitfields); } pktgen_log_info(""); for (sid = 0; sid < wr_coremap_cnt(pktgen.core_info, pktgen.core_cnt, 0); sid++) pktgen_packet_capture_init(&pktgen.capture[sid], sid); }
void pktgen_print_packet_dump(void) { port_info_t *info; unsigned int pid; unsigned int i, j; unsigned char *pdata; uint32_t plen; char buff[4096]; for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { if (wr_get_map(pktgen.l2p, pid, RTE_MAX_LCORE) == 0) continue; info = &pktgen.info[pid]; for (; info->dump_head < info->dump_tail; ++info->dump_head) { pdata = (unsigned char *)info->dump_list[info-> dump_head ].data; plen = info->dump_list[info->dump_head].len; snprintf(buff, sizeof(buff), "Port %d, packet with length %d:", pid, plen); for (i = 0; i < plen; i += 16) { strncatf(buff, "\n\t"); /* Byte counter */ strncatf(buff, "%06x: ", i); for (j = 0; j < 16; ++j) { /* Hex. value of character */ if (i + j < plen) strncatf(buff, "%02x ", pdata[i + j]); else strncatf(buff, " "); /* Extra padding after 8 hex values for readability */ if ((j + 1) % 8 == 0) strncatf(buff, " "); } /* Separate hex. values and raw characters */ strncatf(buff, "\t"); for (j = 0; j < 16; ++j) if (i + j < plen) strncatf(buff, "%c", isprint(pdata[i + j]) ? pdata[ i + j] : '.'); } pktgen_log_info("%s", buff); rte_free(info->dump_list[info->dump_head].data); info->dump_list[info->dump_head].data = NULL; } } }
int wr_parse_matrix(l2p_t * l2p, char * str) { char * lcore_port[MAX_MATRIX_ENTRIES]; char buff[256]; int i, m, k, lid_type, pid_type; uint32_t pid, lid; lp_t lp; rxtx_t cnt, n; wr_strccpy(buff, str, " \r\n\t\""); // Split up the string into <lcore-port>, ... k = wr_strparse(buff, ",", lcore_port, countof(lcore_port)); if ( k <= 0 ) { fprintf(stderr, "%s: could not parse (%s) string\n", __FUNCTION__, buff); return 0; } for(i = 0; (i < k) && lcore_port[i]; i++) { char * arr[3]; char str[64]; // Grab a private copy of the string. strncpy(str, lcore_port[i], sizeof(str)); // Parse the string into <lcore-list> and <port-list> m = wr_strparse( lcore_port[i], ".", arr, 3 ); if ( m != 2 ) { fprintf(stderr, "%s: could not parse <lcore-list>.<port-list> (%s) string\n", __FUNCTION__, lcore_port[i]); return 0; } memset(&lp, '\0', sizeof(lp)); if ( wr_parse_lp_list(arr[0], lp.lcores) ) { fprintf(stderr, "%s: could not parse <lcore-list> (%s) string\n", __FUNCTION__, arr[0]); return 0; } if ( wr_parse_lp_list(arr[1], lp.ports) ) { fprintf(stderr, "%s: could not parse <port-list> (%s) string\n", __FUNCTION__, arr[1]); return 0; } // Handle the lcore and port list maps fprintf(stderr, "%-16s = lcores(rx %016lx, tx %016lx) ports(rx %016lx, tx %016lx)\n", str, lp.lcores[RX_IDX], lp.lcores[TX_IDX], lp.ports[RX_IDX], lp.ports[TX_IDX]); for(lid = 0; lid < RTE_MAX_LCORE; lid++) { lid_type = 0; if ( (lp.lcores[RX_IDX] & (1ULL << lid)) != 0 ) lid_type |= RX_TYPE; if ( (lp.lcores[TX_IDX] & (1ULL << lid)) != 0 ) lid_type |= TX_TYPE; if ( lid_type == 0 ) continue; for(pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { pid_type = 0; if ( (lp.ports[RX_IDX] & (1ULL << pid)) != 0 ) pid_type |= RX_TYPE; if ( (lp.ports[TX_IDX] & (1ULL << pid)) != 0 ) pid_type |= TX_TYPE; if ( pid_type == 0 ) continue; wr_l2p_connect(l2p, pid, lid, lid_type); } } } for(pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { n.rxtx = 0; for(lid = 0; lid < RTE_MAX_LCORE; lid++) { if ( (cnt.rxtx = wr_get_map(l2p, pid, lid)) > 0) { if ( cnt.tx > 0 ) n.tx++; if ( cnt.rx > 0 ) n.rx++; } } l2p->map[pid][lid].rxtx = n.rxtx; // Update the lcores per port } for(lid = 0; lid < RTE_MAX_LCORE; lid++) { n.rxtx = 0; for(pid = 0; pid < RTE_MAX_ETHPORTS; pid++) { if ( (cnt.rxtx = wr_get_map(l2p, pid, lid)) > 0) { if ( cnt.tx > 0 ) n.tx++; if ( cnt.rx > 0 ) n.rx++; } } l2p->map[pid][lid].rxtx = n.rxtx; // Update the ports per lcore } return 0; }