From patchwork Thu Nov 18 18:56:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elena Agostini X-Patchwork-Id: 104509 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4E4F3A0C41; Thu, 18 Nov 2021 11:45:55 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 76C0B41142; Thu, 18 Nov 2021 11:45:50 +0100 (CET) Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2046.outbound.protection.outlook.com [40.107.236.46]) by mails.dpdk.org (Postfix) with ESMTP id 27E4740395 for ; Thu, 18 Nov 2021 11:45:48 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Z0FRpM1HXfGpejRgQ9t0kK5vy4cgq2oY9cqvF9NAs58WH+nSs6dtwtQvxn4KQYSqQCpLOhBLI61MnmWtbNoWyo2vPatthEjSgtPX/XuQsnJqUanY9vDsXJZlmrMOzOhFrAthesb5zL3qmVV06bJ2f3G/Jy48HJKFG33Xfzx39n28JhvGEAQKGPw7Yil5uC0tCfDMPoXuabazwWGVuYVr6Yr1gFwGcIOqM0vpyuSsLRR2jG9plDxx7wZgY5vrs7xtO2I5YewydMYW6hSImeEc0aBILvrDfG7+NduJewczLNnwVy/Tl+G06A7deqzWlyjXPAk4gXyPPpH1pcg6TnNQ9g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=0LiwciIYPo6u4DxDgd7JQARuLALZv7tSQWeja1iFU1E=; b=l7bUyQ6g50FNQM9aOrE559gYkDE023iy3DuaBq0z+rdA3+oALVVAGtqa8oI9inakE8CBhLYQQyeGE8OqmPDvChauFA0lHVSoBRRPDCBkgkrVNNZ3AgU7n+CjKFfxYiwG1/4Pp+nc+78j5Z5c5ZB59Hob+gcNTFVpbQims6m+ra/o2UIRDuLxdl4Qp9zS1KcOO4Ziu18VyYcGx32C2WYVxg/2icPRTuuXYYPONO7UnbKn1HPdudV+vBnL4S1U4xcbz48TuaudWOYLnw/TkSDw6UcNM414sd36TjuG7bwe+Y5YY/xl2pzTZjEXKNTxwFGILS4rH60ovhg+ah7Fu+K/Bw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.112.34) smtp.rcpttodomain=dpdk.org smtp.mailfrom=nvidia.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0LiwciIYPo6u4DxDgd7JQARuLALZv7tSQWeja1iFU1E=; b=irGkGM0vJU+njGqXUXdKZmg96lvXdcT5f+328R/vNRfxkVyORe7Z6Gx03YLkjIatlj72EZ8X0JfKjAVQK01Qkcs64cq8Y7Rm1NuHXpF1rrwypgZnS5D5BRO4VcTc1nUtlcUXDALr6ZvLnuWmbccz0a8EqOefADUSYSK9Ek6F0NHsULU+NTpDJcQFCd24f1pBjfQIXQ2wqvUBhsgYmoo5fxaMSi40HncsQIuLJQgIB1Y47qNVzEooy1d5BstpIzK1NWfUGNWniu6cfmHrdbjLdM/fzAlmBXqaZO9njruEJaPcjkNhGqjXROOc3muaHpnb6NjBSvtHmt57N8xsxrmxVA== Received: from MW2PR16CA0033.namprd16.prod.outlook.com (2603:10b6:907::46) by CY4PR1201MB2532.namprd12.prod.outlook.com (2603:10b6:903:d8::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.19; Thu, 18 Nov 2021 10:45:45 +0000 Received: from CO1NAM11FT008.eop-nam11.prod.protection.outlook.com (2603:10b6:907:0:cafe::5c) by MW2PR16CA0033.outlook.office365.com (2603:10b6:907::46) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4690.27 via Frontend Transport; Thu, 18 Nov 2021 10:45:45 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.112.34) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.112.34 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.112.34; helo=mail.nvidia.com; Received: from mail.nvidia.com (216.228.112.34) by CO1NAM11FT008.mail.protection.outlook.com (10.13.175.191) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4713.20 via Frontend Transport; Thu, 18 Nov 2021 10:45:45 +0000 Received: from nvidia.com (172.20.187.6) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Thu, 18 Nov 2021 10:45:40 +0000 From: To: CC: Elena Agostini Subject: [PATCH v2 1/1] app/test-gpudev: introduce ethdev to rx/tx packets using GPU memory Date: Thu, 18 Nov 2021 18:56:13 +0000 Message-ID: <20211118185613.3246-2-eagostini@nvidia.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211118185613.3246-1-eagostini@nvidia.com> References: <20211118015228.30628-1-eagostini@nvidia.com> <20211118185613.3246-1-eagostini@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [172.20.187.6] X-ClientProxiedBy: HQMAIL111.nvidia.com (172.20.187.18) To HQMAIL107.nvidia.com (172.20.187.13) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 8233591d-b7fb-4ce3-d0ec-08d9aa80933a X-MS-TrafficTypeDiagnostic: CY4PR1201MB2532: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:125; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: /UXXUGCRtroj++4WNIYjWk3AuAT/sjiBhvLpK7vBv6albgVZp5jniri5slEJza9G+UchcOLWXTYeIuxum6S4koiTUBeGKXp8ffGiLEbb/EveO2BxIfnwa+9LHKeL6Xn1uXf+4jdZ0Gr6C9U2Cs4ftbomOR+s+PSVGjiNIf5u7cIZkzlzKdG1K9lL6liBhbxFs/u/bcAeVbeuG6+f+2u9sK9dHAmXKlpBnqSMz47b9oronf0nGFaaYJHjJYsZqtUjZsM7CjDP4Gz78NwxhulQT085Yx2KhBmXPhaYGeSYp/JygT+EgQSpZi+u2Jf6ErGQzTF8GSDqarTHvaZv16qG8WPREdFb9mX8tfMuWx0YJZmSGo3/gptaoDgH610knvl5liRmL3GqPWHgENc/Fk1HyVypom6LluXUW3pe1q7MbuO/NG4KIC6/yyiDFFLCMSVkA9LD2D5UV5dn/9ktCSfF807fyY9D/OHKV/sQArO9br4gp5eUgiE+CNbW2fcpEx9/qhKf4IofsWmkYnsVAoRWmsUAG5T5PZ7393s0YI/S6ggyytuQsW4E4Sb9NcA03Y6jq8LyGHAkj/7Yr1LmiEYaWssTxTaEFav3udBRtX02Yp0PSjQ1tqUZp2O13D2DjX10XcgvAHSIRwmaugjKN7zwRU6X3ySuNzNRg8+OZh0i7v7GpUhMJLRWkfkOBaTX3BgE9kwuEgPtMK4tpUe6OqdURw== X-Forefront-Antispam-Report: CIP:216.228.112.34; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:schybrid03.nvidia.com; CAT:NONE; SFS:(4636009)(36840700001)(46966006)(26005)(1076003)(8676002)(8936002)(4326008)(6286002)(336012)(36860700001)(426003)(36756003)(7696005)(7636003)(16526019)(47076005)(186003)(2616005)(6916009)(86362001)(5660300002)(508600001)(82310400003)(70586007)(70206006)(356005)(2876002)(2906002)(83380400001)(36906005)(6666004)(107886003)(30864003)(55016002)(316002); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2021 10:45:45.1237 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8233591d-b7fb-4ce3-d0ec-08d9aa80933a X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.112.34]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT008.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR1201MB2532 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Elena Agostini This patch introduces ethdev in test-gpudev app to provide: - an example to show how GPU memory can be used to send and receive packets - an useful tool to measure network metrics when using GPU memory with io forwarding With this feature test-gpudev can: - RX packets in CPU or GPU memory - Store packets in the gpudev communication list - TX receive packets from the communication list It's a simulation of a multi-core application. Signed-off-by: Elena Agostini --- app/test-gpudev/main.c | 477 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 458 insertions(+), 19 deletions(-) diff --git a/app/test-gpudev/main.c b/app/test-gpudev/main.c index 250fba6427..18de023208 100644 --- a/app/test-gpudev/main.c +++ b/app/test-gpudev/main.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -19,22 +21,90 @@ #include #include #include +#include +#include +#include #include +#define GPU_PAGE_SHIFT 16 +#define GPU_PAGE_SIZE (1UL << GPU_PAGE_SHIFT) +#define GPU_PAGE_OFFSET (GPU_PAGE_SIZE-1) +#define GPU_PAGE_MASK (~GPU_PAGE_OFFSET) + +#define MAX_QUEUES 16 +#define NUM_COMM_ITEMS 2048 +#define PKT_GAP 4 + +// #define DEBUG_PRINT 1 + enum app_args { ARG_HELP, - ARG_MEMPOOL + ARG_BURST, + ARG_GPU, + ARG_MBUFD, + ARG_MEMORY, + ARG_QUEUES, + ARG_TESTAPI, +}; + +enum mem_type { + MEMORY_CPU, + MEMORY_GPU +}; + +/* Options configurable from cmd line */ +static uint32_t conf_burst = 64; +static uint16_t conf_gpu_id = 0; +static enum mem_type conf_mtype = MEMORY_CPU; +static uint32_t conf_mbuf_dataroom = 2048; +static uint32_t conf_queues = 1; +static bool conf_testapi = false; +static uint16_t conf_nb_descriptors = 2048; + +/* Options statically defined */ +static uint32_t conf_nb_mbuf = 16384; +static uint16_t conf_port_id = 0; + +/* Other variables */ +static volatile bool force_quit; +static struct rte_mempool *mpool; +static struct rte_pktmbuf_extmem ext_mem; +struct rte_gpu_comm_list *comm_list_fwd[MAX_QUEUES]; +struct rte_ether_addr port_eth_addr; +static struct rte_eth_conf port_conf = { + .rxmode = { + .mq_mode = ETH_MQ_RX_RSS, + .split_hdr_size = 0, + .offloads = 0, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + .offloads = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = ETH_RSS_IP + }, + }, }; static void usage(const char *prog_name) { - printf("%s [EAL options] --\n", + printf("%s [EAL options] --\n" + " --help\n" + " --burst N: number of packets per rx burst\n" + " --gpu N: GPU ID to use\n" + " --memory N: external mempool memory type, 0 CPU, 1 GPU\n" + " --mbufd N: mbuf dataroom size\n" + " --testapi: test gpudev function\n" + " --queues N: number of RX queues\n", prog_name); } -static void +static int args_parse(int argc, char **argv) { char **argvopt; @@ -42,7 +112,19 @@ args_parse(int argc, char **argv) int opt_idx; static struct option lgopts[] = { - { "help", 0, 0, ARG_HELP}, + { "help", 0, 0, ARG_HELP}, + /* Packets per burst. */ + { "burst", 1, 0, ARG_BURST}, + /* GPU to use. */ + { "gpu", 1, 0, ARG_GPU}, + /* Type of memory for the mempool. */ + { "memory", 1, 0, ARG_MEMORY}, + /* Size of mbufs dataroom */ + { "mbufd", 1, 0, ARG_MBUFD}, + /* Number of RX queues */ + { "queues", 1, 0, ARG_QUEUES}, + /* Test only gpudev functions */ + { "testapi", 0, 0, ARG_TESTAPI}, /* End of options */ { 0, 0, 0, 0 } }; @@ -51,6 +133,24 @@ args_parse(int argc, char **argv) while ((opt = getopt_long(argc, argvopt, "", lgopts, &opt_idx)) != EOF) { switch (opt) { + case ARG_BURST: + conf_burst = (uint32_t) atoi(optarg); + break; + case ARG_GPU: + conf_gpu_id = (uint16_t) atoi(optarg); + break; + case ARG_MEMORY: + conf_mtype = (atoi(optarg) == 1 ? MEMORY_GPU : MEMORY_CPU); + break; + case ARG_MBUFD: + conf_mbuf_dataroom = (uint32_t) atoi(optarg); + break; + case ARG_QUEUES: + conf_queues = (uint32_t) atoi(optarg); + break; + case ARG_TESTAPI: + conf_testapi = (atoi(optarg) == 1 ? true : false); + break; case ARG_HELP: usage(argv[0]); break; @@ -60,6 +160,19 @@ args_parse(int argc, char **argv) break; } } + + if (conf_queues > MAX_QUEUES) { + fprintf(stderr, "Can't support more than %d queues\n", MAX_QUEUES); + return -1; + } + + if (conf_queues * 2 > rte_lcore_count()) { + fprintf(stderr, "Need to use at least %d cores to support %d RX/TX queues (EAL cores %d)\n", + conf_queues * 2, conf_queues, rte_lcore_count()); + return -1; + } + + return 0; } static int @@ -342,13 +455,130 @@ create_update_comm_list(uint16_t gpu_id) return -1; } +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", + signum); + force_quit = true; + } +} + +static int +rx_core(__rte_unused void *arg) +{ + uint32_t queue_id; + uint32_t nb_rx = 0; + int ret = 0; + int comm_list_item = 0; + struct rte_mbuf *rx_mbufs[RTE_GPU_COMM_LIST_PKTS_MAX]; + + queue_id = (rte_lcore_index(rte_lcore_id()) - 1) / 2; + + if (queue_id > conf_queues) { + fprintf(stderr, "Please specify the right list of cores (%d cores) in EAL params to support %d queues.\n", + conf_queues*2, conf_queues); + RTE_GPU_VOLATILE(force_quit) = true; + return -1; + } + + printf("RX core started on queue %d.\n", queue_id); + + while (force_quit == false) { + + nb_rx = 0; + while (nb_rx < RTE_GPU_COMM_LIST_PKTS_MAX && + nb_rx < (conf_burst - PKT_GAP) && + force_quit == false) { + nb_rx += rte_eth_rx_burst(conf_port_id, queue_id, + &(rx_mbufs[nb_rx]), + (conf_burst - nb_rx)); + } + + ret = rte_gpu_comm_populate_list_pkts( + &(comm_list_fwd[queue_id][comm_list_item]), rx_mbufs, nb_rx); + if (ret) { + fprintf(stderr, "rte_gpu_comm_populate_list_pkts error %d.\n", ret); + return -1; + } + +#ifdef DEBUG_PRINT + printf("RX %d pkts from item %d\n", + comm_list_fwd[queue_id][comm_list_item].num_pkts, + comm_list_item); +#endif + + RTE_GPU_VOLATILE(comm_list_fwd[queue_id][comm_list_item].status) = RTE_GPU_COMM_LIST_DONE; + + comm_list_item = (comm_list_item+1) % NUM_COMM_ITEMS; + } + + return 0; +} + +static int +tx_core(__rte_unused void *arg) +{ + uint32_t queue_id = 0; + uint32_t nb_tx = 0; + int ret = 0; + int comm_list_item = 0; + + queue_id = (rte_lcore_index(rte_lcore_id()) - 1) / 2; + if (queue_id > conf_queues) { + fprintf(stderr, "Please specify the right list of cores (%d cores) in EAL params to support %d queues.\n", + conf_queues*2, conf_queues); + RTE_GPU_VOLATILE(force_quit) = true; + return -1; + } + printf("TX core started on queue %d.\n", queue_id); + + while (force_quit == false) { + +#ifdef DEBUG_PRINT + printf("Waiting on item %d\n", comm_list_item); +#endif + while (RTE_GPU_VOLATILE(comm_list_fwd[queue_id][comm_list_item].status) != + RTE_GPU_COMM_LIST_DONE && force_quit == false); + + nb_tx = 0; + while (nb_tx < comm_list_fwd[queue_id][comm_list_item].num_pkts) { + nb_tx += rte_eth_tx_burst(conf_port_id, queue_id, + &(comm_list_fwd[queue_id][comm_list_item].mbufs[nb_tx]), + comm_list_fwd[queue_id][comm_list_item].num_pkts - nb_tx); + } + rte_wmb(); + +#ifdef DEBUG_PRINT + printf("TX %d/%d pkts from item %d\n", + nb_tx, comm_list_fwd[queue_id][comm_list_item].num_pkts, + comm_list_item); +#endif + ret = rte_gpu_comm_cleanup_list(&(comm_list_fwd[queue_id][comm_list_item])); + if (ret) { + fprintf(stderr, "rte_gpu_comm_cleanup_list error %d.\n", ret); + return -1; + } + + rte_mb(); + + comm_list_item = (comm_list_item+1) % NUM_COMM_ITEMS; + } + + return 0; +} + int main(int argc, char **argv) { - int ret; + int ret, core_id; int nb_gpus = 0; + int nb_ports = 0; int16_t gpu_id = 0; + uint32_t idx_q = 0; struct rte_gpu_info ginfo; + struct rte_eth_dev_info dev_info; /* Init EAL. */ ret = rte_eal_init(argc, argv); @@ -356,8 +586,14 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "EAL init failed\n"); argc -= ret; argv += ret; - if (argc > 1) - args_parse(argc, argv); + if (argc > 1) { + ret = args_parse(argc, argv); + if (ret) { + fprintf(stderr, "Input args error.\n"); + goto exit; + } + } + argc -= ret; argv += ret; @@ -381,25 +617,228 @@ main(int argc, char **argv) if (nb_gpus == 0) { fprintf(stderr, "Need at least one GPU on the system to run the example\n"); - return EXIT_FAILURE; + goto exit; } - gpu_id = 0; + if (nb_gpus < conf_gpu_id) { + fprintf(stderr, "Not enough GPUs in the system (%d / %d).\n", nb_gpus, conf_gpu_id); + goto exit; + } - /** - * Memory tests - */ - alloc_gpu_memory(gpu_id); - register_cpu_memory(gpu_id); + if (conf_testapi == true) { + /* Memory tests */ + alloc_gpu_memory(gpu_id); + register_cpu_memory(gpu_id); - /** - * Communication items test - */ - create_update_comm_flag(gpu_id); - create_update_comm_list(gpu_id); + /* Communication items test */ + create_update_comm_flag(gpu_id); + create_update_comm_list(gpu_id); + + goto exit; + } + + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports == 0) + rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); + + ret = rte_eth_dev_info_get(conf_port_id, &dev_info); + if (ret) { + fprintf(stderr, "rte_eth_dev_info_get failed with %d.\n", ret); + goto exit; + } + + /* Create external memory mempool. */ + ext_mem.elt_size = conf_mbuf_dataroom + RTE_PKTMBUF_HEADROOM; + ext_mem.buf_len = RTE_ALIGN_CEIL(conf_nb_mbuf * ext_mem.elt_size, GPU_PAGE_SIZE); + + if (conf_mtype == MEMORY_CPU) { + ext_mem.buf_ptr = rte_malloc("extmem", ext_mem.buf_len, 0); + if (ext_mem.buf_ptr == NULL) { + fprintf(stderr, "Could not allocate CPU DPDK memory.\n"); + goto exit; + } + + ret = rte_gpu_mem_register(conf_gpu_id, ext_mem.buf_len, ext_mem.buf_ptr); + if (ret < 0) { + fprintf(stderr, + "rte_gpu_mem_register CPU memory returned error %d.\n", ret); + return -1; + } + } else { + ext_mem.buf_iova = RTE_BAD_IOVA; + + ext_mem.buf_ptr = rte_gpu_mem_alloc(conf_gpu_id, ext_mem.buf_len); + if (ext_mem.buf_ptr == NULL) { + fprintf(stderr, "Could not allocate GPU device memory.\n"); + goto exit; + } + + ret = rte_extmem_register(ext_mem.buf_ptr, ext_mem.buf_len, + NULL, ext_mem.buf_iova, GPU_PAGE_SIZE); + if (ret) { + fprintf(stderr, "Unable to register addr 0x%p, ret %d.\n", ext_mem.buf_ptr, ret); + goto exit; + } + } + + /* DMA map the external memory. */ + ret = rte_dev_dma_map(dev_info.device, ext_mem.buf_ptr, + ext_mem.buf_iova, ext_mem.buf_len); + if (ret) { + fprintf(stderr, "Could not DMA map EXT memory.\n"); + goto exit; + } + + /* Create external memory mempool. */ + mpool = rte_pktmbuf_pool_create_extbuf("payload_mpool", conf_nb_mbuf, + 0, 0, ext_mem.elt_size, + rte_socket_id(), &ext_mem, 1); + if (mpool == NULL) { + fprintf(stderr, "Could not create EXT memory mempool.\n"); + goto exit; + } + + /* Queues configuration. */ + ret = rte_eth_dev_configure(conf_port_id, conf_queues, + conf_queues, &port_conf); + if (ret < 0) { + fprintf(stderr, + "Cannot configure device: err=%d, port=%u queues=%u\n", + ret, conf_port_id, conf_queues); + goto exit; + } + + ret = rte_eth_dev_adjust_nb_rx_tx_desc(conf_port_id, + &conf_nb_descriptors, &conf_nb_descriptors); + if (ret) { + fprintf(stderr, + "Cannot adjust number of descriptors: err=%d, port=%u\n", + ret, conf_port_id); + goto exit; + } + + for (idx_q = 0; idx_q < conf_queues; idx_q++) { + + ret = rte_eth_rx_queue_setup(conf_port_id, idx_q, + conf_nb_descriptors, rte_lcore_to_socket_id(idx_q), + NULL, mpool); + + if (ret) { + fprintf(stderr, "rte_eth_rx_queue_setup: err=%d, port=%u\n", + ret, conf_port_id); + goto exit; + } + + ret = rte_eth_tx_queue_setup(conf_port_id, idx_q, + conf_nb_descriptors, rte_lcore_to_socket_id(idx_q), NULL); + if (ret) { + fprintf(stderr, "rte_eth_tx_queue_setup: err=%d, port=%u\n", + ret, conf_port_id); + goto exit; + } + } + + rte_eth_macaddr_get(conf_port_id, &port_eth_addr); + + ret = rte_eth_dev_start(conf_port_id); + if (ret) { + fprintf(stderr, "rte_eth_dev_start: err=%d, port=%u\n", + ret, conf_port_id); + goto exit; + } + + printf("Port %d: %02x:%02x:%02x:%02x:%02x:%02x started!\n", + conf_port_id, + (uint8_t)port_eth_addr.addr_bytes[0], + (uint8_t)port_eth_addr.addr_bytes[1], + port_eth_addr.addr_bytes[2], + port_eth_addr.addr_bytes[3], + port_eth_addr.addr_bytes[4], + port_eth_addr.addr_bytes[5]); + + rte_eth_promiscuous_enable(conf_port_id); + + /* Create communication lists, one per queue. */ + for (idx_q = 0; idx_q < MAX_QUEUES; idx_q++) { + comm_list_fwd[idx_q] = NULL; + + if (idx_q < conf_queues) { + comm_list_fwd[idx_q] = rte_gpu_comm_create_list(conf_gpu_id, + NUM_COMM_ITEMS); + if (comm_list_fwd[idx_q] == NULL) { + fprintf(stderr, "comm_create_list returned error %d\n", + ret); + goto exit; + } + ret = rte_gpu_comm_cleanup_list(&(comm_list_fwd[idx_q][0])); + if (ret < 0) { + fprintf(stderr, "comm_cleanup_list returned error %d\n", + ret); + goto exit; + } + } + } + + core_id = 0; + for (idx_q = 0; idx_q < conf_queues; idx_q++) { + core_id = rte_get_next_lcore(core_id, 1, 0); + rte_eal_remote_launch(tx_core, NULL, core_id); + + core_id = rte_get_next_lcore(core_id, 1, 0); + rte_eal_remote_launch(rx_core, NULL, core_id); + } + + core_id = 0; + RTE_LCORE_FOREACH_WORKER(core_id) { + if (rte_eal_wait_lcore(core_id) < 0) { + fprintf(stderr, "bad exit for core %d.\n", + core_id); + break; + } + } + + force_quit = true; + + ret = rte_dev_dma_unmap(dev_info.device, (void *)ext_mem.buf_ptr, + RTE_BAD_IOVA, ext_mem.buf_len); + if (ret) { + fprintf(stderr, + "rte_dev_dma_unmap 0x%p -> %d (rte_errno = %d)\n", + (uint8_t *)ext_mem.buf_ptr, ret, rte_errno); + goto exit; + } + + if (conf_mtype == MEMORY_CPU) { + ret = rte_gpu_mem_unregister(conf_gpu_id, ext_mem.buf_ptr); + if (ret < 0) { + fprintf(stderr, "rte_gpu_mem_unregister returned error %d\n", ret); + goto exit; + } + + rte_free(ext_mem.buf_ptr); + + } else { + + ret = rte_extmem_unregister(ext_mem.buf_ptr, ext_mem.buf_len); + if (ret) { + fprintf(stderr, "rte_extmem_unregister failed with %d.\n", ret); + goto exit; + } + + rte_gpu_mem_free(conf_gpu_id, (void *)ext_mem.buf_ptr); + } + + rte_eth_dev_stop(conf_port_id); + rte_eth_dev_close(conf_port_id); +exit: /* clean up the EAL */ rte_eal_cleanup(); + printf("Bye...\n"); return EXIT_SUCCESS; }