1d4ab30baSDaniel Verkamp /*- 2d4ab30baSDaniel Verkamp * BSD LICENSE 3d4ab30baSDaniel Verkamp * 4d4ab30baSDaniel Verkamp * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. 5d4ab30baSDaniel Verkamp * All rights reserved. 6d4ab30baSDaniel Verkamp * 7d4ab30baSDaniel Verkamp * Redistribution and use in source and binary forms, with or without 8d4ab30baSDaniel Verkamp * modification, are permitted provided that the following conditions 9d4ab30baSDaniel Verkamp * are met: 10d4ab30baSDaniel Verkamp * 11d4ab30baSDaniel Verkamp * * Redistributions of source code must retain the above copyright 12d4ab30baSDaniel Verkamp * notice, this list of conditions and the following disclaimer. 13d4ab30baSDaniel Verkamp * * Redistributions in binary form must reproduce the above copyright 14d4ab30baSDaniel Verkamp * notice, this list of conditions and the following disclaimer in 15d4ab30baSDaniel Verkamp * the documentation and/or other materials provided with the 16d4ab30baSDaniel Verkamp * distribution. 17d4ab30baSDaniel Verkamp * * Neither the name of Intel Corporation nor the names of its 18d4ab30baSDaniel Verkamp * contributors may be used to endorse or promote products derived 19d4ab30baSDaniel Verkamp * from this software without specific prior written permission. 20d4ab30baSDaniel Verkamp * 21d4ab30baSDaniel Verkamp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22d4ab30baSDaniel Verkamp * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23d4ab30baSDaniel Verkamp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24d4ab30baSDaniel Verkamp * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25d4ab30baSDaniel Verkamp * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26d4ab30baSDaniel Verkamp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27d4ab30baSDaniel Verkamp * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28d4ab30baSDaniel Verkamp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29d4ab30baSDaniel Verkamp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30d4ab30baSDaniel Verkamp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31d4ab30baSDaniel Verkamp * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32d4ab30baSDaniel Verkamp */ 33d4ab30baSDaniel Verkamp 34d4ab30baSDaniel Verkamp #include <stdio.h> 35d4ab30baSDaniel Verkamp #include <unistd.h> 36d4ab30baSDaniel Verkamp #include <stdlib.h> 37d4ab30baSDaniel Verkamp #include <stdbool.h> 38d4ab30baSDaniel Verkamp #include <string.h> 39d4ab30baSDaniel Verkamp #include <rte_config.h> 40d4ab30baSDaniel Verkamp #include <rte_malloc.h> 41d4ab30baSDaniel Verkamp #include <rte_eal.h> 42d4ab30baSDaniel Verkamp #include <rte_lcore.h> 43d4ab30baSDaniel Verkamp #include <rte_cycles.h> 44d4ab30baSDaniel Verkamp #include <rte_mempool.h> 45d4ab30baSDaniel Verkamp #include <pciaccess.h> 46d4ab30baSDaniel Verkamp #include "spdk/ioat.h" 47d4ab30baSDaniel Verkamp #include "spdk/pci.h" 48d4ab30baSDaniel Verkamp #include "spdk/string.h" 49d4ab30baSDaniel Verkamp 50d4ab30baSDaniel Verkamp struct user_config { 51d4ab30baSDaniel Verkamp int xfer_size_bytes; 52d4ab30baSDaniel Verkamp int queue_depth; 53d4ab30baSDaniel Verkamp int time_in_sec; 54d4ab30baSDaniel Verkamp bool verify; 55d4ab30baSDaniel Verkamp char *core_mask; 56d4ab30baSDaniel Verkamp }; 57d4ab30baSDaniel Verkamp 58d4ab30baSDaniel Verkamp struct ioat_device { 59d4ab30baSDaniel Verkamp struct ioat_channel *ioat; 60d4ab30baSDaniel Verkamp TAILQ_ENTRY(ioat_device) tailq; 61d4ab30baSDaniel Verkamp }; 62d4ab30baSDaniel Verkamp 63d4ab30baSDaniel Verkamp static TAILQ_HEAD(, ioat_device) g_devices; 64d4ab30baSDaniel Verkamp 65d4ab30baSDaniel Verkamp static struct user_config g_user_config; 66d4ab30baSDaniel Verkamp 67d4ab30baSDaniel Verkamp struct thread_entry { 68d4ab30baSDaniel Verkamp uint64_t xfer_completed; 69d4ab30baSDaniel Verkamp uint64_t xfer_failed; 70d4ab30baSDaniel Verkamp uint64_t current_queue_depth; 71d4ab30baSDaniel Verkamp unsigned lcore_id; 72d4ab30baSDaniel Verkamp bool is_draining; 73d4ab30baSDaniel Verkamp struct rte_mempool *data_pool; 74d4ab30baSDaniel Verkamp struct rte_mempool *task_pool; 75d4ab30baSDaniel Verkamp }; 76d4ab30baSDaniel Verkamp 77d4ab30baSDaniel Verkamp struct ioat_task { 78d4ab30baSDaniel Verkamp struct thread_entry *thread_entry; 79d4ab30baSDaniel Verkamp void *src; 80d4ab30baSDaniel Verkamp void *dst; 81d4ab30baSDaniel Verkamp }; 82d4ab30baSDaniel Verkamp 83d4ab30baSDaniel Verkamp static void submit_single_xfer(struct thread_entry *thread_entry, struct ioat_task *ioat_task, 84d4ab30baSDaniel Verkamp void *dst, void *src); 85d4ab30baSDaniel Verkamp 86d4ab30baSDaniel Verkamp static void 87d4ab30baSDaniel Verkamp construct_user_config(struct user_config *self) 88d4ab30baSDaniel Verkamp { 89d4ab30baSDaniel Verkamp self->xfer_size_bytes = 4096; 90d4ab30baSDaniel Verkamp self->queue_depth = 256; 91d4ab30baSDaniel Verkamp self->time_in_sec = 10; 92d4ab30baSDaniel Verkamp self->verify = false; 93d4ab30baSDaniel Verkamp self->core_mask = "0x1"; 94d4ab30baSDaniel Verkamp } 95d4ab30baSDaniel Verkamp 96d4ab30baSDaniel Verkamp static void 97d4ab30baSDaniel Verkamp dump_user_config(struct user_config *self) 98d4ab30baSDaniel Verkamp { 99d4ab30baSDaniel Verkamp printf("User configuration:\n"); 100d4ab30baSDaniel Verkamp printf("Transfer size: %u bytes\n", self->xfer_size_bytes); 101d4ab30baSDaniel Verkamp printf("Queue depth: %u\n", self->queue_depth); 102d4ab30baSDaniel Verkamp printf("Run time: %u seconds\n", self->time_in_sec); 103d4ab30baSDaniel Verkamp printf("Core mask: %s\n", self->core_mask); 104d4ab30baSDaniel Verkamp printf("Verify: %s\n\n", self->verify ? "Yes" : "No"); 105d4ab30baSDaniel Verkamp } 106d4ab30baSDaniel Verkamp 107d4ab30baSDaniel Verkamp static void 108d4ab30baSDaniel Verkamp ioat_exit(void) 109d4ab30baSDaniel Verkamp { 110d4ab30baSDaniel Verkamp struct ioat_device *dev; 111d4ab30baSDaniel Verkamp 112d4ab30baSDaniel Verkamp while (!TAILQ_EMPTY(&g_devices)) { 113d4ab30baSDaniel Verkamp dev = TAILQ_FIRST(&g_devices); 114d4ab30baSDaniel Verkamp TAILQ_REMOVE(&g_devices, dev, tailq); 115*25cad6ffSDaniel Verkamp if (dev->ioat) { 116d4ab30baSDaniel Verkamp ioat_detach(dev->ioat); 117*25cad6ffSDaniel Verkamp } 118d4ab30baSDaniel Verkamp rte_free(dev); 119d4ab30baSDaniel Verkamp } 120d4ab30baSDaniel Verkamp } 121d4ab30baSDaniel Verkamp 122d4ab30baSDaniel Verkamp static void 123d4ab30baSDaniel Verkamp ioat_done(void *cb_arg) 124d4ab30baSDaniel Verkamp { 125d4ab30baSDaniel Verkamp struct ioat_task *ioat_task = (struct ioat_task *)cb_arg; 126d4ab30baSDaniel Verkamp struct thread_entry *thread_entry = ioat_task->thread_entry; 127d4ab30baSDaniel Verkamp 128d4ab30baSDaniel Verkamp if (g_user_config.verify && memcmp(ioat_task->src, ioat_task->dst, g_user_config.xfer_size_bytes)) { 129d4ab30baSDaniel Verkamp thread_entry->xfer_failed++; 130d4ab30baSDaniel Verkamp } else { 131d4ab30baSDaniel Verkamp thread_entry->xfer_completed++; 132d4ab30baSDaniel Verkamp } 133d4ab30baSDaniel Verkamp 134d4ab30baSDaniel Verkamp thread_entry->current_queue_depth--; 135d4ab30baSDaniel Verkamp 136d4ab30baSDaniel Verkamp if (thread_entry->is_draining) { 137d4ab30baSDaniel Verkamp rte_mempool_put(thread_entry->data_pool, ioat_task->src); 138d4ab30baSDaniel Verkamp rte_mempool_put(thread_entry->data_pool, ioat_task->dst); 139d4ab30baSDaniel Verkamp rte_mempool_put(thread_entry->task_pool, ioat_task); 140d4ab30baSDaniel Verkamp } else { 141d4ab30baSDaniel Verkamp submit_single_xfer(thread_entry, ioat_task, ioat_task->dst, ioat_task->src); 142d4ab30baSDaniel Verkamp } 143d4ab30baSDaniel Verkamp } 144d4ab30baSDaniel Verkamp 145d4ab30baSDaniel Verkamp static int 146d4ab30baSDaniel Verkamp ioat_init(void) 147d4ab30baSDaniel Verkamp { 148d4ab30baSDaniel Verkamp struct pci_device_iterator *iter; 149d4ab30baSDaniel Verkamp struct pci_device *pci_dev; 150d4ab30baSDaniel Verkamp int err = 0; 151d4ab30baSDaniel Verkamp struct pci_id_match match; 152d4ab30baSDaniel Verkamp struct ioat_device *dev; 153d4ab30baSDaniel Verkamp 154d4ab30baSDaniel Verkamp pci_system_init(); 155d4ab30baSDaniel Verkamp TAILQ_INIT(&g_devices); 156d4ab30baSDaniel Verkamp 157d4ab30baSDaniel Verkamp match.vendor_id = PCI_MATCH_ANY; 158d4ab30baSDaniel Verkamp match.subvendor_id = PCI_MATCH_ANY; 159d4ab30baSDaniel Verkamp match.subdevice_id = PCI_MATCH_ANY; 160d4ab30baSDaniel Verkamp match.device_id = PCI_MATCH_ANY; 161d4ab30baSDaniel Verkamp match.device_class = 0x088000; 162d4ab30baSDaniel Verkamp match.device_class_mask = 0xFFFFFF; 163d4ab30baSDaniel Verkamp 164d4ab30baSDaniel Verkamp iter = pci_id_match_iterator_create(&match); 165d4ab30baSDaniel Verkamp 166d4ab30baSDaniel Verkamp while ((pci_dev = pci_device_next(iter)) != NULL) { 167d4ab30baSDaniel Verkamp /* Check if the PCI devices is a supported IOAT channel. */ 168d4ab30baSDaniel Verkamp if (!(ioat_pci_device_match_id(pci_dev->vendor_id, 169d4ab30baSDaniel Verkamp pci_dev->device_id))) { 170d4ab30baSDaniel Verkamp continue; 171d4ab30baSDaniel Verkamp } 172d4ab30baSDaniel Verkamp 173d4ab30baSDaniel Verkamp printf(" Found matching device at %d:%d:%d " 174d4ab30baSDaniel Verkamp "vendor:0x%04x device:0x%04x\n name:%s\n", 175d4ab30baSDaniel Verkamp pci_dev->bus, pci_dev->dev, pci_dev->func, 176d4ab30baSDaniel Verkamp pci_dev->vendor_id, pci_dev->device_id, 177d4ab30baSDaniel Verkamp pci_device_get_device_name(pci_dev)); 178d4ab30baSDaniel Verkamp 179d4ab30baSDaniel Verkamp if (pci_device_has_non_null_driver(pci_dev)) { 180d4ab30baSDaniel Verkamp printf("Device has kernel driver, skipping...\n"); 181d4ab30baSDaniel Verkamp continue; 182d4ab30baSDaniel Verkamp } 183d4ab30baSDaniel Verkamp 184d4ab30baSDaniel Verkamp pci_device_probe(pci_dev); 185d4ab30baSDaniel Verkamp 186d4ab30baSDaniel Verkamp dev = rte_malloc(NULL, sizeof(*dev), 0); 187d4ab30baSDaniel Verkamp if (dev == NULL) { 188d4ab30baSDaniel Verkamp printf("Failed to allocate device struct\n"); 189d4ab30baSDaniel Verkamp err = -1; 190d4ab30baSDaniel Verkamp goto cleanup; 191d4ab30baSDaniel Verkamp } 192d4ab30baSDaniel Verkamp 193d4ab30baSDaniel Verkamp dev->ioat = ioat_attach(pci_dev); 194d4ab30baSDaniel Verkamp if (dev->ioat == NULL) { 195d4ab30baSDaniel Verkamp rte_free(dev); 196d4ab30baSDaniel Verkamp /* Likely no device found. */ 197d4ab30baSDaniel Verkamp err = -1; 198d4ab30baSDaniel Verkamp goto cleanup; 199d4ab30baSDaniel Verkamp } 200d4ab30baSDaniel Verkamp TAILQ_INSERT_TAIL(&g_devices, dev, tailq); 201d4ab30baSDaniel Verkamp } 202d4ab30baSDaniel Verkamp 203d4ab30baSDaniel Verkamp cleanup: 204d4ab30baSDaniel Verkamp pci_iterator_destroy(iter); 205d4ab30baSDaniel Verkamp if (err != 0) { 206d4ab30baSDaniel Verkamp ioat_exit(); 207d4ab30baSDaniel Verkamp } 208d4ab30baSDaniel Verkamp return 0; 209d4ab30baSDaniel Verkamp } 210d4ab30baSDaniel Verkamp 211d4ab30baSDaniel Verkamp static void 212d4ab30baSDaniel Verkamp usage(char *program_name) 213d4ab30baSDaniel Verkamp { 214d4ab30baSDaniel Verkamp printf("%s options\n", program_name); 215d4ab30baSDaniel Verkamp printf("\t[-h help message]\n"); 216d4ab30baSDaniel Verkamp printf("\t[-c core mask for distributing I/O submission/completion work]\n"); 217d4ab30baSDaniel Verkamp printf("\t[-q queue depth]\n"); 218d4ab30baSDaniel Verkamp printf("\t[-s transfer size in bytes]\n"); 219d4ab30baSDaniel Verkamp printf("\t[-t time in seconds]\n"); 220d4ab30baSDaniel Verkamp printf("\t[-v verify copy result if this switch is on]\n"); 221d4ab30baSDaniel Verkamp } 222d4ab30baSDaniel Verkamp 223d4ab30baSDaniel Verkamp static int 224d4ab30baSDaniel Verkamp parse_args(int argc, char **argv) 225d4ab30baSDaniel Verkamp { 226d4ab30baSDaniel Verkamp int op; 227d4ab30baSDaniel Verkamp 228d4ab30baSDaniel Verkamp construct_user_config(&g_user_config); 229d4ab30baSDaniel Verkamp while ((op = getopt(argc, argv, "c:hq:s:t:v")) != -1) { 230d4ab30baSDaniel Verkamp switch (op) { 231d4ab30baSDaniel Verkamp case 's': 232d4ab30baSDaniel Verkamp g_user_config.xfer_size_bytes = atoi(optarg); 233d4ab30baSDaniel Verkamp break; 234d4ab30baSDaniel Verkamp case 'q': 235d4ab30baSDaniel Verkamp g_user_config.queue_depth = atoi(optarg); 236d4ab30baSDaniel Verkamp break; 237d4ab30baSDaniel Verkamp case 't': 238d4ab30baSDaniel Verkamp g_user_config.time_in_sec = atoi(optarg); 239d4ab30baSDaniel Verkamp break; 240d4ab30baSDaniel Verkamp case 'c': 241d4ab30baSDaniel Verkamp g_user_config.core_mask = optarg; 242d4ab30baSDaniel Verkamp break; 243d4ab30baSDaniel Verkamp case 'v': 244d4ab30baSDaniel Verkamp g_user_config.verify = true; 245d4ab30baSDaniel Verkamp break; 246d4ab30baSDaniel Verkamp case 'h': 247d4ab30baSDaniel Verkamp usage(argv[0]); 248d4ab30baSDaniel Verkamp exit(0); 249d4ab30baSDaniel Verkamp default: 250d4ab30baSDaniel Verkamp usage(argv[0]); 251d4ab30baSDaniel Verkamp return 1; 252d4ab30baSDaniel Verkamp } 253d4ab30baSDaniel Verkamp } 254d4ab30baSDaniel Verkamp if (!g_user_config.xfer_size_bytes || !g_user_config.queue_depth || 255d4ab30baSDaniel Verkamp !g_user_config.time_in_sec || !g_user_config.core_mask) { 256d4ab30baSDaniel Verkamp usage(argv[0]); 257d4ab30baSDaniel Verkamp return 1; 258d4ab30baSDaniel Verkamp } 259d4ab30baSDaniel Verkamp optind = 1; 260d4ab30baSDaniel Verkamp return 0; 261d4ab30baSDaniel Verkamp } 262d4ab30baSDaniel Verkamp 263d4ab30baSDaniel Verkamp static void 264d4ab30baSDaniel Verkamp drain_io(struct thread_entry *thread_entry) 265d4ab30baSDaniel Verkamp { 266d4ab30baSDaniel Verkamp while (thread_entry->current_queue_depth > 0) { 267d4ab30baSDaniel Verkamp ioat_process_events(); 268d4ab30baSDaniel Verkamp } 269d4ab30baSDaniel Verkamp } 270d4ab30baSDaniel Verkamp 271d4ab30baSDaniel Verkamp static void 272d4ab30baSDaniel Verkamp submit_single_xfer(struct thread_entry *thread_entry, struct ioat_task *ioat_task, void *dst, 273d4ab30baSDaniel Verkamp void *src) 274d4ab30baSDaniel Verkamp { 275d4ab30baSDaniel Verkamp ioat_task->thread_entry = thread_entry; 276d4ab30baSDaniel Verkamp ioat_task->src = src; 277d4ab30baSDaniel Verkamp ioat_task->dst = dst; 278d4ab30baSDaniel Verkamp 279d4ab30baSDaniel Verkamp ioat_submit_copy(ioat_task, ioat_done, dst, src, g_user_config.xfer_size_bytes); 280d4ab30baSDaniel Verkamp 281d4ab30baSDaniel Verkamp thread_entry->current_queue_depth++; 282d4ab30baSDaniel Verkamp } 283d4ab30baSDaniel Verkamp 284d4ab30baSDaniel Verkamp static void 285d4ab30baSDaniel Verkamp submit_xfers(struct thread_entry *thread_entry, uint64_t queue_depth) 286d4ab30baSDaniel Verkamp { 287d4ab30baSDaniel Verkamp while (queue_depth-- > 0) { 288d4ab30baSDaniel Verkamp void *src = NULL, *dst = NULL; 289d4ab30baSDaniel Verkamp struct ioat_task *ioat_task = NULL; 290d4ab30baSDaniel Verkamp 291d4ab30baSDaniel Verkamp rte_mempool_get(thread_entry->data_pool, &src); 292d4ab30baSDaniel Verkamp rte_mempool_get(thread_entry->data_pool, &dst); 293d4ab30baSDaniel Verkamp rte_mempool_get(thread_entry->task_pool, (void **)&ioat_task); 294d4ab30baSDaniel Verkamp 295d4ab30baSDaniel Verkamp submit_single_xfer(thread_entry, ioat_task, dst, src); 296d4ab30baSDaniel Verkamp } 297d4ab30baSDaniel Verkamp } 298d4ab30baSDaniel Verkamp 299d4ab30baSDaniel Verkamp static int 300d4ab30baSDaniel Verkamp work_fn(void *arg) 301d4ab30baSDaniel Verkamp { 302d4ab30baSDaniel Verkamp char buf_pool_name[20], task_pool_name[20]; 303d4ab30baSDaniel Verkamp uint64_t tsc_end; 304d4ab30baSDaniel Verkamp struct thread_entry *t = (struct thread_entry *)arg; 305d4ab30baSDaniel Verkamp 306d4ab30baSDaniel Verkamp t->lcore_id = rte_lcore_id(); 307d4ab30baSDaniel Verkamp 308d4ab30baSDaniel Verkamp snprintf(buf_pool_name, sizeof(buf_pool_name), "buf_pool_%d", rte_lcore_id()); 309d4ab30baSDaniel Verkamp snprintf(task_pool_name, sizeof(task_pool_name), "task_pool_%d", rte_lcore_id()); 310d4ab30baSDaniel Verkamp t->data_pool = rte_mempool_create(buf_pool_name, 512, g_user_config.xfer_size_bytes, 0, 0, NULL, 311d4ab30baSDaniel Verkamp NULL, 312d4ab30baSDaniel Verkamp NULL, NULL, SOCKET_ID_ANY, 0); 313d4ab30baSDaniel Verkamp t->task_pool = rte_mempool_create(task_pool_name, 512, sizeof(struct ioat_task), 0, 0, NULL, NULL, 314d4ab30baSDaniel Verkamp NULL, NULL, SOCKET_ID_ANY, 0); 315d4ab30baSDaniel Verkamp if (!t->data_pool || !t->task_pool) { 316d4ab30baSDaniel Verkamp fprintf(stderr, "Could not allocate buffer pool.\n"); 317d4ab30baSDaniel Verkamp return 1; 318d4ab30baSDaniel Verkamp } 319d4ab30baSDaniel Verkamp 320d4ab30baSDaniel Verkamp if (ioat_register_thread() != 0) { 321d4ab30baSDaniel Verkamp fprintf(stderr, "lcore %u: No ioat channels found. Check that ioatdma driver is unloaded.\n", 322d4ab30baSDaniel Verkamp rte_lcore_id()); 323d4ab30baSDaniel Verkamp return 0; 324d4ab30baSDaniel Verkamp } 325d4ab30baSDaniel Verkamp 326d4ab30baSDaniel Verkamp tsc_end = rte_get_timer_cycles() + g_user_config.time_in_sec * rte_get_timer_hz(); 327d4ab30baSDaniel Verkamp 328d4ab30baSDaniel Verkamp // begin to submit transfers 329d4ab30baSDaniel Verkamp submit_xfers(t, g_user_config.queue_depth); 330d4ab30baSDaniel Verkamp while (rte_get_timer_cycles() < tsc_end) { 331d4ab30baSDaniel Verkamp ioat_process_events(); 332d4ab30baSDaniel Verkamp } 333d4ab30baSDaniel Verkamp 334d4ab30baSDaniel Verkamp // begin to drain io 335d4ab30baSDaniel Verkamp t->is_draining = true; 336d4ab30baSDaniel Verkamp drain_io(t); 337d4ab30baSDaniel Verkamp ioat_unregister_thread(); 338d4ab30baSDaniel Verkamp 339d4ab30baSDaniel Verkamp return 0; 340d4ab30baSDaniel Verkamp } 341d4ab30baSDaniel Verkamp 342d4ab30baSDaniel Verkamp static int 343d4ab30baSDaniel Verkamp init(void) 344d4ab30baSDaniel Verkamp { 345d4ab30baSDaniel Verkamp char *core_mask_conf; 346d4ab30baSDaniel Verkamp 347d4ab30baSDaniel Verkamp core_mask_conf = sprintf_alloc("-c %s", g_user_config.core_mask); 348d4ab30baSDaniel Verkamp if (!core_mask_conf) { 349d4ab30baSDaniel Verkamp return 1; 350d4ab30baSDaniel Verkamp } 351d4ab30baSDaniel Verkamp 352d4ab30baSDaniel Verkamp char *ealargs[] = {"perf", core_mask_conf, "-n 4", "--no-pci"}; 353d4ab30baSDaniel Verkamp 354d4ab30baSDaniel Verkamp if (rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs) < 0) { 355d4ab30baSDaniel Verkamp free(core_mask_conf); 356d4ab30baSDaniel Verkamp fprintf(stderr, "Could not init eal\n"); 357d4ab30baSDaniel Verkamp return 1; 358d4ab30baSDaniel Verkamp } 359d4ab30baSDaniel Verkamp 360d4ab30baSDaniel Verkamp free(core_mask_conf); 361d4ab30baSDaniel Verkamp 362d4ab30baSDaniel Verkamp if (ioat_init() != 0) { 363d4ab30baSDaniel Verkamp fprintf(stderr, "Could not init ioat\n"); 364d4ab30baSDaniel Verkamp return 1; 365d4ab30baSDaniel Verkamp } 366d4ab30baSDaniel Verkamp 367d4ab30baSDaniel Verkamp return 0; 368d4ab30baSDaniel Verkamp } 369d4ab30baSDaniel Verkamp 370d4ab30baSDaniel Verkamp static int 371d4ab30baSDaniel Verkamp dump_result(struct thread_entry *threads, int len) 372d4ab30baSDaniel Verkamp { 373d4ab30baSDaniel Verkamp int i; 374d4ab30baSDaniel Verkamp uint64_t total_completed = 0; 375d4ab30baSDaniel Verkamp uint64_t total_failed = 0; 376d4ab30baSDaniel Verkamp uint64_t total_xfer_per_sec, total_bw_in_MBps; 377d4ab30baSDaniel Verkamp 378d4ab30baSDaniel Verkamp printf("lcore Transfers Bandwidth Failed\n"); 379d4ab30baSDaniel Verkamp printf("--------------------------------------------\n"); 380d4ab30baSDaniel Verkamp for (i = 0; i < len; i++) { 381d4ab30baSDaniel Verkamp struct thread_entry *t = &threads[i]; 382d4ab30baSDaniel Verkamp 383d4ab30baSDaniel Verkamp uint64_t xfer_per_sec = t->xfer_completed / g_user_config.time_in_sec; 384d4ab30baSDaniel Verkamp uint64_t bw_in_MBps = (t->xfer_completed * g_user_config.xfer_size_bytes) / 385d4ab30baSDaniel Verkamp (g_user_config.time_in_sec * 1024 * 1024); 386d4ab30baSDaniel Verkamp 387d4ab30baSDaniel Verkamp total_completed += t->xfer_completed; 388d4ab30baSDaniel Verkamp total_failed += t->xfer_failed; 389d4ab30baSDaniel Verkamp 390d4ab30baSDaniel Verkamp if (xfer_per_sec) { 391d4ab30baSDaniel Verkamp printf("%5d %10" PRIu64 "/s %10" PRIu64 " MB/s %6" PRIu64 "\n", 392d4ab30baSDaniel Verkamp t->lcore_id, xfer_per_sec, bw_in_MBps, t->xfer_failed); 393d4ab30baSDaniel Verkamp } 394d4ab30baSDaniel Verkamp } 395d4ab30baSDaniel Verkamp 396d4ab30baSDaniel Verkamp total_xfer_per_sec = total_completed / g_user_config.time_in_sec; 397d4ab30baSDaniel Verkamp total_bw_in_MBps = (total_completed * g_user_config.xfer_size_bytes) / 398d4ab30baSDaniel Verkamp (g_user_config.time_in_sec * 1024 * 1024); 399d4ab30baSDaniel Verkamp 400d4ab30baSDaniel Verkamp printf("============================================\n"); 401d4ab30baSDaniel Verkamp printf("Total: %10" PRIu64 "/s %10" PRIu64 " MB/s %6" PRIu64 "\n", 402d4ab30baSDaniel Verkamp total_xfer_per_sec, total_bw_in_MBps, total_failed); 403d4ab30baSDaniel Verkamp return total_failed ? 1 : 0; 404d4ab30baSDaniel Verkamp } 405d4ab30baSDaniel Verkamp 406d4ab30baSDaniel Verkamp int 407d4ab30baSDaniel Verkamp main(int argc, char **argv) 408d4ab30baSDaniel Verkamp { 409d4ab30baSDaniel Verkamp unsigned lcore_id; 410d4ab30baSDaniel Verkamp struct thread_entry threads[RTE_MAX_LCORE] = {}; 411*25cad6ffSDaniel Verkamp int rc; 412d4ab30baSDaniel Verkamp 413d4ab30baSDaniel Verkamp if (parse_args(argc, argv) != 0) { 414d4ab30baSDaniel Verkamp return 1; 415d4ab30baSDaniel Verkamp } 416d4ab30baSDaniel Verkamp 417d4ab30baSDaniel Verkamp if (init() != 0) { 418d4ab30baSDaniel Verkamp return 1; 419d4ab30baSDaniel Verkamp } 420d4ab30baSDaniel Verkamp 421d4ab30baSDaniel Verkamp dump_user_config(&g_user_config); 422d4ab30baSDaniel Verkamp 423d4ab30baSDaniel Verkamp RTE_LCORE_FOREACH_SLAVE(lcore_id) { 424d4ab30baSDaniel Verkamp rte_eal_remote_launch(work_fn, &threads[lcore_id], lcore_id); 425d4ab30baSDaniel Verkamp } 426d4ab30baSDaniel Verkamp 427d4ab30baSDaniel Verkamp if (work_fn(&threads[rte_get_master_lcore()]) != 0) { 428*25cad6ffSDaniel Verkamp rc = 1; 429*25cad6ffSDaniel Verkamp goto cleanup; 430d4ab30baSDaniel Verkamp } 431d4ab30baSDaniel Verkamp 432d4ab30baSDaniel Verkamp RTE_LCORE_FOREACH_SLAVE(lcore_id) { 433d4ab30baSDaniel Verkamp if (rte_eal_wait_lcore(lcore_id) != 0) { 434*25cad6ffSDaniel Verkamp rc = 1; 435*25cad6ffSDaniel Verkamp goto cleanup; 436d4ab30baSDaniel Verkamp } 437d4ab30baSDaniel Verkamp } 438d4ab30baSDaniel Verkamp 439*25cad6ffSDaniel Verkamp rc = dump_result(threads, RTE_MAX_LCORE); 440*25cad6ffSDaniel Verkamp 441*25cad6ffSDaniel Verkamp cleanup: 442*25cad6ffSDaniel Verkamp ioat_exit(); 443*25cad6ffSDaniel Verkamp 444*25cad6ffSDaniel Verkamp return rc; 445d4ab30baSDaniel Verkamp } 446