<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:DengXian;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@DengXian";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
        {mso-style-priority:99;
        mso-style-link:"Plain Text Char";
        margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.PlainTextChar
        {mso-style-name:"Plain Text Char";
        mso-style-priority:99;
        mso-style-link:"Plain Text";
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoPlainText">Hi Cheng,<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">LGTM.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">> -----Original Message-----<o:p></o:p></p>
<p class="MsoPlainText">> Date: Wed, 28 Jun 2023 01:20:34 +0000<o:p></o:p></p>
<p class="MsoPlainText">> From: Cheng Jiang <<a href="mailto:cheng1.jiang@intel.com">cheng1.jiang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> To: <a href="mailto:thomas@monjalon.net">thomas@monjalon.net</a>,
<a href="mailto:bruce.richardson@intel.com">bruce.richardson@intel.com</a>,<o:p></o:p></p>
<p class="MsoPlainText">>            <a href="mailto:mb@smartsharesystems.com">mb@smartsharesystems.com</a>,
<a href="mailto:chenbo.xia@intel.com">chenbo.xia@intel.com</a>,<o:p></o:p></p>
<p class="MsoPlainText">>            <a href="mailto:amitprakashs@marvell.com">amitprakashs@marvell.com</a>,
<a href="mailto:anoobj@marvell.com">anoobj@marvell.com</a>, <o:p></o:p></p>
<p class="MsoPlainText">> <a href="mailto:huangdengdui@huawei.com">huangdengdui@huawei.com</a>,<o:p></o:p></p>
<p class="MsoPlainText">>            <a href="mailto:kevin.laatz@intel.com">kevin.laatz@intel.com</a>,
<a href="mailto:fengchengwen@huawei.com">fengchengwen@huawei.com</a>, <a href="mailto:jerinj@marvell.com">
jerinj@marvell.com</a><o:p></o:p></p>
<p class="MsoPlainText">> Cc: <a href="mailto:dev@dpdk.org">dev@dpdk.org</a>, <a href="mailto:jiayu.hu@intel.com">
jiayu.hu@intel.com</a>, <a href="mailto:xuan.ding@intel.com">xuan.ding@intel.com</a>,<o:p></o:p></p>
<p class="MsoPlainText">>            <a href="mailto:wenwux.ma@intel.com">wenwux.ma@intel.com</a>,
<a href="mailto:yuanx.wang@intel.com">yuanx.wang@intel.com</a>, <a href="mailto:xingguang.he@intel.com">
xingguang.he@intel.com</a>,<o:p></o:p></p>
<p class="MsoPlainText">>            <a href="mailto:weix.ling@intel.com">weix.ling@intel.com</a>, Cheng Jiang <<a href="mailto:cheng1.jiang@intel.com">cheng1.jiang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Subject: [PATCH v10] app/dma-perf: introduce dma-perf application<o:p></o:p></p>
<p class="MsoPlainText">> Message-ID: <<a href="mailto:20230628012034.49016-1-cheng1.jiang@intel.com">20230628012034.49016-1-cheng1.jiang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Content-Type: text/plain; charset=UTF-8<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> There are many high-performance DMA devices supported in DPDK now, and
<o:p></o:p></p>
<p class="MsoPlainText">> these DMA devices can also be integrated into other modules of DPDK as
<o:p></o:p></p>
<p class="MsoPlainText">> accelerators, such as Vhost. Before integrating DMA into applications,
<o:p></o:p></p>
<p class="MsoPlainText">> developers need to know the performance of these DMA devices in
<o:p></o:p></p>
<p class="MsoPlainText">> various scenarios and the performance of CPUs in the same scenario,
<o:p></o:p></p>
<p class="MsoPlainText">> such as different buffer lengths. Only in this way can we know the
<o:p></o:p></p>
<p class="MsoPlainText">> target performance of the application accelerated by using them. This
<o:p></o:p></p>
<p class="MsoPlainText">> patch introduces a high-performance testing tool, which supports
<o:p></o:p></p>
<p class="MsoPlainText">> comparing the performance of CPU and DMA in different scenarios
<o:p></o:p></p>
<p class="MsoPlainText">> automatically with a pre-set config file. Memory Copy performance test are supported for now.<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> Signed-off-by: Cheng Jiang <<a href="mailto:cheng1.jiang@intel.com">cheng1.jiang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Signed-off-by: Jiayu Hu <<a href="mailto:jiayu.hu@intel.com">jiayu.hu@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Signed-off-by: Yuan Wang <<a href="mailto:yuanx.wang@intel.com">yuanx.wang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Acked-by: Morten Br?rup <<a href="mailto:mb@smartsharesystems.com">mb@smartsharesystems.com</a>><o:p></o:p></p>
<p class="MsoPlainText">> Acked-by: Chenbo Xia <<a href="mailto:chenbo.xia@intel.com">chenbo.xia@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">Acked-by: Yuying Zhang <<a href="mailto:yuying.zhang@intel.com">yuying.zhang@intel.com</a>><o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">> ---<o:p></o:p></p>
<p class="MsoPlainText">> v10:<o:p></o:p></p>
<p class="MsoPlainText">>   rebased code from 23.07-rc2;<o:p></o:p></p>
<p class="MsoPlainText">> v9:<o:p></o:p></p>
<p class="MsoPlainText">>   improved error handling;<o:p></o:p></p>
<p class="MsoPlainText">>   improved lcore_params structure;<o:p></o:p></p>
<p class="MsoPlainText">>   improved mbuf api calling;<o:p></o:p></p>
<p class="MsoPlainText">>   improved exit process;<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some typos;<o:p></o:p></p>
<p class="MsoPlainText">>   added scenario summary data display;<o:p></o:p></p>
<p class="MsoPlainText">>   removed unnecessary include;<o:p></o:p></p>
<p class="MsoPlainText">> v8:<o:p></o:p></p>
<p class="MsoPlainText">>   fixed string copy issue in parse_lcore();<o:p></o:p></p>
<p class="MsoPlainText">>   improved some data display format;<o:p></o:p></p>
<p class="MsoPlainText">>   added doc in doc/guides/tools;<o:p></o:p></p>
<p class="MsoPlainText">>   updated release notes;<o:p></o:p></p>
<p class="MsoPlainText">> v7:<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some strcpy issues;<o:p></o:p></p>
<p class="MsoPlainText">>   removed cache setup in calling rte_pktmbuf_pool_create();<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some typos;<o:p></o:p></p>
<p class="MsoPlainText">>   added some memory free and null set operations;<o:p></o:p></p>
<p class="MsoPlainText">>   improved result calculation;<o:p></o:p></p>
<p class="MsoPlainText">> v6:<o:p></o:p></p>
<p class="MsoPlainText">>   improved code based on Anoob's comments;<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some code structure issues;<o:p></o:p></p>
<p class="MsoPlainText">> v5:<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some LONG_LINE warnings;<o:p></o:p></p>
<p class="MsoPlainText">> v4:<o:p></o:p></p>
<p class="MsoPlainText">>   fixed inaccuracy of the memory footprint display;<o:p></o:p></p>
<p class="MsoPlainText">> v3:<o:p></o:p></p>
<p class="MsoPlainText">>   fixed some typos;<o:p></o:p></p>
<p class="MsoPlainText">> v2:<o:p></o:p></p>
<p class="MsoPlainText">>   added lcore/dmadev designation;<o:p></o:p></p>
<p class="MsoPlainText">>   added error case process;<o:p></o:p></p>
<p class="MsoPlainText">>   removed worker_threads parameter from config.ini;<o:p></o:p></p>
<p class="MsoPlainText">>   improved the logs;<o:p></o:p></p>
<p class="MsoPlainText">>   improved config file;<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">>  app/meson.build                        |   1 +<o:p></o:p></p>
<p class="MsoPlainText">>  app/test-dma-perf/benchmark.c          | 508 ++++++++++++++++++++<o:p></o:p></p>
<p class="MsoPlainText">>  app/test-dma-perf/config.ini           |  61 +++<o:p></o:p></p>
<p class="MsoPlainText">>  app/test-dma-perf/main.c               | 616 +++++++++++++++++++++++++<o:p></o:p></p>
<p class="MsoPlainText">>  app/test-dma-perf/main.h               |  64 +++<o:p></o:p></p>
<p class="MsoPlainText">>  app/test-dma-perf/meson.build          |  17 +<o:p></o:p></p>
<p class="MsoPlainText">>  doc/guides/rel_notes/release_23_07.rst |   6 +<o:p></o:p></p>
<p class="MsoPlainText">>  doc/guides/tools/dmaperf.rst           | 103 +++++<o:p></o:p></p>
<p class="MsoPlainText">>  doc/guides/tools/index.rst             |   1 +<o:p></o:p></p>
<p class="MsoPlainText">>  9 files changed, 1377 insertions(+)<o:p></o:p></p>
<p class="MsoPlainText">>  create mode 100644 app/test-dma-perf/benchmark.c  create mode 100644
<o:p></o:p></p>
<p class="MsoPlainText">> app/test-dma-perf/config.ini  create mode 100644 <o:p></o:p></p>
<p class="MsoPlainText">> app/test-dma-perf/main.c create mode 100644 app/test-dma-perf/main.h 
<o:p></o:p></p>
<p class="MsoPlainText">> create mode 100644 app/test-dma-perf/meson.build  create mode 100644
<o:p></o:p></p>
<p class="MsoPlainText">> doc/guides/tools/dmaperf.rst<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/meson.build b/app/meson.build index <o:p>
</o:p></p>
<p class="MsoPlainText">> 74d2420f67..4fc1a83eba 100644<o:p></o:p></p>
<p class="MsoPlainText">> --- a/app/meson.build<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/meson.build<o:p></o:p></p>
<p class="MsoPlainText">> @@ -19,6 +19,7 @@ apps = [<o:p></o:p></p>
<p class="MsoPlainText">>          'test-cmdline',<o:p></o:p></p>
<p class="MsoPlainText">>          'test-compress-perf',<o:p></o:p></p>
<p class="MsoPlainText">>          'test-crypto-perf',<o:p></o:p></p>
<p class="MsoPlainText">> +        'test-dma-perf',<o:p></o:p></p>
<p class="MsoPlainText">>          'test-eventdev',<o:p></o:p></p>
<p class="MsoPlainText">>          'test-fib',<o:p></o:p></p>
<p class="MsoPlainText">>          'test-flow-perf',<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/test-dma-perf/benchmark.c b/app/test-dma-
<o:p></o:p></p>
<p class="MsoPlainText">> perf/benchmark.c new file mode 100644 index 0000000000..0601e0d171<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/test-dma-perf/benchmark.c<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,508 @@<o:p></o:p></p>
<p class="MsoPlainText">> +/* SPDX-License-Identifier: BSD-3-Clause<o:p></o:p></p>
<p class="MsoPlainText">> + * Copyright(c) 2023 Intel Corporation  */<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include <inttypes.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <stdio.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <stdlib.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <unistd.h><o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_time.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_mbuf.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_dmadev.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_malloc.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_lcore.h><o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include "main.h"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_DMA_CPL_NB 255<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define TEST_WAIT_U_SECOND 10000<o:p></o:p></p>
<p class="MsoPlainText">> +#define POLL_MAX 1000<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define CSV_LINE_DMA_FMT "Scenario %u,%u,%s,%u,%u,%u,%u,%.2lf,%"<o:p></o:p></p>
<p class="MsoPlainText">> PRIu64 ",%.3lf,%.3lf\n"<o:p></o:p></p>
<p class="MsoPlainText">> +#define CSV_LINE_CPU_FMT "Scenario %u,%u,NA,NA,NA,%u,%u,%.2lf,%"<o:p></o:p></p>
<p class="MsoPlainText">> PRIu64 ",%.3lf,%.3lf\n"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define CSV_TOTAL_LINE_FMT "Scenario %u<o:p></o:p></p>
<p class="MsoPlainText">> Summary, , , , , ,%u,%.2lf,%u,%.3lf,%.3lf\n"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +struct worker_info {<o:p></o:p></p>
<p class="MsoPlainText">> +         bool ready_flag;<o:p></o:p></p>
<p class="MsoPlainText">> +         bool start_flag;<o:p></o:p></p>
<p class="MsoPlainText">> +         bool stop_flag;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t total_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t test_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +};<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +struct lcore_params {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint8_t scenario_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         unsigned int lcore_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *dma_name;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t worker_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t dev_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nr_buf;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t test_secs;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **srcs;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **dsts;<o:p></o:p></p>
<p class="MsoPlainText">> +         volatile struct worker_info worker_info; };<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static struct rte_mempool *src_pool;<o:p></o:p></p>
<p class="MsoPlainText">> +static struct rte_mempool *dst_pool;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static struct lcore_params *lcores[MAX_WORKER_NB];<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define PRINT_ERR(...) print_err(__func__, __LINE__, __VA_ARGS__)<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline int<o:p></o:p></p>
<p class="MsoPlainText">> +__rte_format_printf(3, 4)<o:p></o:p></p>
<p class="MsoPlainText">> +print_err(const char *func, int lineno, const char *format, ...) {<o:p></o:p></p>
<p class="MsoPlainText">> +         va_list ap;<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         ret = fprintf(stderr, "In %s:%d - ", func, lineno);<o:p></o:p></p>
<p class="MsoPlainText">> +         va_start(ap, format);<o:p></o:p></p>
<p class="MsoPlainText">> +         ret += vfprintf(stderr, format, ap);<o:p></o:p></p>
<p class="MsoPlainText">> +         va_end(ap);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return ret;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline void<o:p></o:p></p>
<p class="MsoPlainText">> +calc_result(uint32_t buf_size, uint32_t nr_buf, uint16_t nb_workers,<o:p></o:p></p>
<p class="MsoPlainText">> uint16_t test_secs,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    uint32_t total_cnt, float *memory, uint32_t<o:p></o:p></p>
<p class="MsoPlainText">> *ave_cycle,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    float *bandwidth, float *mops)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         float ops;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         *memory = (float)(buf_size * (nr_buf / nb_workers) * 2) / (1024 *<o:p></o:p></p>
<p class="MsoPlainText">> 1024);<o:p></o:p></p>
<p class="MsoPlainText">> +         *ave_cycle = test_secs * rte_get_timer_hz() / total_cnt;<o:p></o:p></p>
<p class="MsoPlainText">> +         ops = (float)total_cnt / test_secs;<o:p></o:p></p>
<p class="MsoPlainText">> +         *mops = ops / (1000 * 1000);<o:p></o:p></p>
<p class="MsoPlainText">> +         *bandwidth = (ops * buf_size * 8) / (1000 * 1000 * 1000); }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +output_result(uint8_t scenario_id, uint32_t lcore_id, char *dma_name,<o:p></o:p></p>
<p class="MsoPlainText">> uint16_t ring_size,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      uint16_t kick_batch, uint64_t ave_cycle, uint32_t<o:p></o:p></p>
<p class="MsoPlainText">> buf_size, uint32_t nr_buf,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      float memory, float bandwidth, float mops, bool<o:p></o:p></p>
<p class="MsoPlainText">> is_dma) {<o:p></o:p></p>
<p class="MsoPlainText">> +         if (is_dma)<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("lcore %u, DMA %s, DMA Ring Size: %u, Kick Batch<o:p></o:p></p>
<p class="MsoPlainText">> Size: %u.\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    lcore_id, dma_name, ring_size, kick_batch);<o:p></o:p></p>
<p class="MsoPlainText">> +         else<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("lcore %u\n", lcore_id);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Average Cycles/op: %" PRIu64 ", Buffer Size: %u B, Buffer<o:p></o:p></p>
<p class="MsoPlainText">> Number: %u, Memory: %.2lf MB, Frequency: %.3lf Ghz.\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ave_cycle, buf_size, nr_buf, memory,<o:p></o:p></p>
<p class="MsoPlainText">> rte_get_timer_hz()/1000000000.0);<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Average Bandwidth: %.3lf Gbps, MOps: %.3lf\n", bandwidth,
<o:p></o:p></p>
<p class="MsoPlainText">> +mops);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (is_dma)<o:p></o:p></p>
<p class="MsoPlainText">> +                       snprintf(output_str[lcore_id], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> CSV_LINE_DMA_FMT,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      scenario_id, lcore_id, dma_name, ring_size,<o:p></o:p></p>
<p class="MsoPlainText">> kick_batch, buf_size,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nr_buf, memory, ave_cycle, bandwidth, mops);<o:p></o:p></p>
<p class="MsoPlainText">> +         else<o:p></o:p></p>
<p class="MsoPlainText">> +                       snprintf(output_str[lcore_id], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> CSV_LINE_CPU_FMT,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      scenario_id, lcore_id, buf_size,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nr_buf, memory, ave_cycle, bandwidth, mops); }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline void<o:p></o:p></p>
<p class="MsoPlainText">> +cache_flush_buf(__rte_unused struct rte_mbuf **array,<o:p></o:p></p>
<p class="MsoPlainText">> +                       __rte_unused uint32_t buf_size,<o:p></o:p></p>
<p class="MsoPlainText">> +                       __rte_unused uint32_t nr_buf)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +#ifdef RTE_ARCH_X86_64<o:p></o:p></p>
<p class="MsoPlainText">> +         char *data;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **srcs = array;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i, offset;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nr_buf; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       data = rte_pktmbuf_mtod(srcs[i], char *);<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (offset = 0; offset < buf_size; offset += 64)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      __builtin_ia32_clflush(data + offset);<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +#endif<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +/* Configuration of device. */<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +configure_dmadev_queue(uint32_t dev_id, uint32_t ring_size) {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t vchan = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_dma_info info;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_dma_conf dev_config = { .nb_vchans = 1 };<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_dma_vchan_conf qconf = {<o:p></o:p></p>
<p class="MsoPlainText">> +                       .direction = RTE_DMA_DIR_MEM_TO_MEM,<o:p></o:p></p>
<p class="MsoPlainText">> +                       .nb_desc = ring_size<o:p></o:p></p>
<p class="MsoPlainText">> +         };<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_dma_configure(dev_id, &dev_config) != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_exit(EXIT_FAILURE, "Error with dma configure.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_dma_vchan_setup(dev_id, vchan, &qconf) != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_exit(EXIT_FAILURE, "Error with queue configuration.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_dma_info_get(dev_id, &info) != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_exit(EXIT_FAILURE, "Error with getting device info.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (info.nb_vchans != 1)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_exit(EXIT_FAILURE, "Error, no configured queues<o:p></o:p></p>
<p class="MsoPlainText">> reported on device id. %u\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    dev_id);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_dma_start(dev_id) != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_exit(EXIT_FAILURE, "Error with dma start.\n"); }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static int<o:p></o:p></p>
<p class="MsoPlainText">> +config_dmadevs(struct test_configure *cfg) {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t ring_size = cfg->ring_size.cur;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_dma_map_t *ldm = &cfg->lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nb_workers = ldm->cnt;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +         int dev_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t nb_dmadevs = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *dma_name;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < ldm->cnt; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       dma_name = ldm->dma_names[i];<o:p></o:p></p>
<p class="MsoPlainText">> +                       dev_id = rte_dma_get_dev_id_by_name(dma_name);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (dev_id < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(stderr, "Error: Fail to find DMA %s.\n",<o:p></o:p></p>
<p class="MsoPlainText">> dma_name);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      goto end;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       ldm->dma_ids[i] = dev_id;<o:p></o:p></p>
<p class="MsoPlainText">> +                       configure_dmadev_queue(dev_id, ring_size);<o:p></o:p></p>
<p class="MsoPlainText">> +                       ++nb_dmadevs;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +end:<o:p></o:p></p>
<p class="MsoPlainText">> +         if (nb_dmadevs < nb_workers) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Not enough dmadevs (%u) for all workers (%u).\n",<o:p></o:p></p>
<p class="MsoPlainText">> nb_dmadevs, nb_workers);<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Number of used dmadevs: %u.\n", nb_dmadevs);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +error_exit(int dev_id)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_dma_stop(dev_id);<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_dma_close(dev_id);<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_exit(EXIT_FAILURE, "DMA error\n"); }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline void<o:p></o:p></p>
<p class="MsoPlainText">> +do_dma_submit_and_poll(uint16_t dev_id, uint64_t *async_cnt,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      volatile struct worker_info *worker_info) {<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t nr_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         ret = rte_dma_submit(dev_id, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (ret < 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       error_exit(dev_id);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         nr_cpl = rte_dma_completed(dev_id, 0, MAX_DMA_CPL_NB, NULL,<o:p></o:p></p>
<p class="MsoPlainText">> NULL);<o:p></o:p></p>
<p class="MsoPlainText">> +         *async_cnt -= nr_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +         worker_info->total_cpl += nr_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline int<o:p></o:p></p>
<p class="MsoPlainText">> +do_dma_mem_copy(void *p)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_params *para = (struct lcore_params *)p;<o:p></o:p></p>
<p class="MsoPlainText">> +         volatile struct worker_info *worker_info = &(para->worker_info);<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint16_t dev_id = para->dev_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint32_t nr_buf = para->nr_buf;<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint16_t kick_batch = para->kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint32_t buf_size = para->buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **srcs = para->srcs;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **dsts = para->dsts;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t nr_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint64_t async_cnt = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t poll_cnt = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         worker_info->stop_flag = false;<o:p></o:p></p>
<p class="MsoPlainText">> +         worker_info->ready_flag = true;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (!worker_info->start_flag)<o:p></o:p></p>
<p class="MsoPlainText">> +                       ;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (i = 0; i < nr_buf; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +dma_copy:<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = rte_dma_copy(dev_id, 0,<o:p></o:p></p>
<p class="MsoPlainText">> rte_mbuf_data_iova(srcs[i]),<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    rte_mbuf_data_iova(dsts[i]), buf_size, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (unlikely(ret < 0)) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    if (ret == -ENOSPC) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   do_dma_submit_and_poll(dev_id,<o:p></o:p></p>
<p class="MsoPlainText">> &async_cnt, worker_info);<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   goto dma_copy;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    } else<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   error_exit(dev_id);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                                      async_cnt++;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if ((async_cnt % kick_batch) == 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    do_dma_submit_and_poll(dev_id,<o:p></o:p></p>
<p class="MsoPlainText">> &async_cnt, worker_info);<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (worker_info->stop_flag)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_dma_submit(dev_id, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         while ((async_cnt > 0) && (poll_cnt++ < POLL_MAX)) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       nr_cpl = rte_dma_completed(dev_id, 0, MAX_DMA_CPL_NB,<o:p></o:p></p>
<p class="MsoPlainText">> NULL, NULL);<o:p></o:p></p>
<p class="MsoPlainText">> +                       async_cnt -= nr_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static inline int<o:p></o:p></p>
<p class="MsoPlainText">> +do_cpu_mem_copy(void *p)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_params *para = (struct lcore_params *)p;<o:p></o:p></p>
<p class="MsoPlainText">> +         volatile struct worker_info *worker_info = &(para->worker_info);<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint32_t nr_buf = para->nr_buf;<o:p></o:p></p>
<p class="MsoPlainText">> +         const uint32_t buf_size = para->buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **srcs = para->srcs;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **dsts = para->dsts;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         worker_info->stop_flag = false;<o:p></o:p></p>
<p class="MsoPlainText">> +         worker_info->ready_flag = true;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (!worker_info->start_flag)<o:p></o:p></p>
<p class="MsoPlainText">> +                       ;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (i = 0; i < nr_buf; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      /* copy buffer form src to dst */<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rte_memcpy((void<o:p></o:p></p>
<p class="MsoPlainText">> *)(uintptr_t)rte_mbuf_data_iova(dsts[i]),<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    (void<o:p></o:p></p>
<p class="MsoPlainText">> *)(uintptr_t)rte_mbuf_data_iova(srcs[i]),<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    (size_t)buf_size);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      worker_info->total_cpl++;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (worker_info->stop_flag)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static int<o:p></o:p></p>
<p class="MsoPlainText">> +setup_memory_env(struct test_configure *cfg, struct rte_mbuf ***srcs,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      struct rte_mbuf ***dsts)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         unsigned int buf_size = cfg->buf_size.cur;<o:p></o:p></p>
<p class="MsoPlainText">> +         unsigned int nr_sockets;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nr_buf = cfg->nr_buf;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         nr_sockets = rte_socket_count();<o:p></o:p></p>
<p class="MsoPlainText">> +         if (cfg->src_numa_node >= nr_sockets ||<o:p></o:p></p>
<p class="MsoPlainText">> +                       cfg->dst_numa_node >= nr_sockets) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Error: Source or destination numa exceeds the acture<o:p></o:p></p>
<p class="MsoPlainText">> numa nodes.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         src_pool = rte_pktmbuf_pool_create("Benchmark_DMA_SRC",<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nr_buf,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      0,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      0,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      buf_size + RTE_PKTMBUF_HEADROOM,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      cfg->src_numa_node);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (src_pool == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       PRINT_ERR("Error with source mempool creation.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         dst_pool = rte_pktmbuf_pool_create("Benchmark_DMA_DST",<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nr_buf,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      0,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      0,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      buf_size + RTE_PKTMBUF_HEADROOM,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      cfg->dst_numa_node);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (dst_pool == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       PRINT_ERR("Error with destination mempool creation.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         *srcs = rte_malloc(NULL, nr_buf * sizeof(struct rte_mbuf *), 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (*srcs == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Error: srcs malloc failed.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         *dsts = rte_malloc(NULL, nr_buf * sizeof(struct rte_mbuf *), 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (*dsts == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Error: dsts malloc failed.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_pktmbuf_alloc_bulk(src_pool, *srcs, nr_buf) != 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("alloc src mbufs failed.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rte_pktmbuf_alloc_bulk(dst_pool, *dsts, nr_buf) != 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("alloc dst mbufs failed.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +void<o:p></o:p></p>
<p class="MsoPlainText">> +mem_copy_benchmark(struct test_configure *cfg, bool is_dma) {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t offset;<o:p></o:p></p>
<p class="MsoPlainText">> +         unsigned int lcore_id = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_mbuf **srcs = NULL, **dsts = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_dma_map_t *ldm = &cfg->lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +         unsigned int buf_size = cfg->buf_size.cur;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t kick_batch = cfg->kick_batch.cur;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nr_buf = cfg->nr_buf = (cfg->mem_size.cur * 1024 * 1024) /<o:p></o:p></p>
<p class="MsoPlainText">> (cfg->buf_size.cur * 2);<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t nb_workers = ldm->cnt;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t test_secs = cfg->test_secs;<o:p></o:p></p>
<p class="MsoPlainText">> +         float memory = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t avg_cycles = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t avg_cycles_total;<o:p></o:p></p>
<p class="MsoPlainText">> +         float mops, mops_total;<o:p></o:p></p>
<p class="MsoPlainText">> +         float bandwidth, bandwidth_total;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (setup_memory_env(cfg, &srcs, &dsts) < 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (is_dma)<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (config_dmadevs(cfg) < 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (cfg->cache_flush == 1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       cache_flush_buf(srcs, buf_size, nr_buf);<o:p></o:p></p>
<p class="MsoPlainText">> +                       cache_flush_buf(dsts, buf_size, nr_buf);<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_mb();<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Start testing....\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_id = ldm->lcores[i];<o:p></o:p></p>
<p class="MsoPlainText">> +                       offset = nr_buf / nb_workers * i;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i] = rte_malloc(NULL, sizeof(struct lcore_params), 0);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (lcores[i] == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("lcore parameters malloc failure for<o:p></o:p></p>
<p class="MsoPlainText">> lcore %d\n", lcore_id);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (is_dma) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                     lcores[i]->dma_name = ldm->dma_names[i];<o:p></o:p></p>
<p class="MsoPlainText">> +                                      lcores[i]->dev_id = ldm->dma_ids[i];<o:p></o:p></p>
<p class="MsoPlainText">> +                                      lcores[i]->kick_batch = kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->worker_id = i;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->nr_buf = (uint32_t)(nr_buf / nb_workers);<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->buf_size = buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->test_secs = test_secs;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->srcs = srcs + offset;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->dsts = dsts + offset;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->scenario_id = cfg->scenario_id;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->lcore_id = lcore_id;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (is_dma)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rte_eal_remote_launch(do_dma_mem_copy, (void<o:p></o:p></p>
<p class="MsoPlainText">> *)(lcores[i]), lcore_id);<o:p></o:p></p>
<p class="MsoPlainText">> +                       else<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rte_eal_remote_launch(do_cpu_mem_copy, (void<o:p></o:p></p>
<p class="MsoPlainText">> *)(lcores[i]), lcore_id);<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       bool ready = true;<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (i = 0; i < nb_workers; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (lcores[i]->worker_info.ready_flag == false) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    ready = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    break;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (ready)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->worker_info.start_flag = true;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         usleep(TEST_WAIT_U_SECOND);<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->worker_info.test_cpl = lcores[i]-<o:p></o:p></p>
<p class="MsoPlainText">> >worker_info.total_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         usleep(test_secs * 1000 * 1000);<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->worker_info.test_cpl = lcores[i]-<o:p></o:p></p>
<p class="MsoPlainText">> >worker_info.total_cpl -<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                                 lcores[i]-<o:p></o:p></p>
<p class="MsoPlainText">> >worker_info.test_cpl;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i]->worker_info.stop_flag = true;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_eal_mp_wait_lcore();<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         mops_total = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         bandwidth_total = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         avg_cycles_total = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       calc_result(buf_size, nr_buf, nb_workers, test_secs,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      lcores[i]->worker_info.test_cpl,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      &memory, &avg_cycles, &bandwidth, &mops);<o:p></o:p></p>
<p class="MsoPlainText">> +                       output_result(cfg->scenario_id, lcores[i]->lcore_id,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   lcores[i]->dma_name, cfg-<o:p></o:p></p>
<p class="MsoPlainText">> >ring_size.cur, kick_batch,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   avg_cycles, buf_size, nr_buf /<o:p></o:p></p>
<p class="MsoPlainText">> nb_workers, memory,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   bandwidth, mops, is_dma);<o:p></o:p></p>
<p class="MsoPlainText">> +                       mops_total += mops;<o:p></o:p></p>
<p class="MsoPlainText">> +                       bandwidth_total += bandwidth;<o:p></o:p></p>
<p class="MsoPlainText">> +                       avg_cycles_total += avg_cycles;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("\nTotal Bandwidth: %.3lf Gbps, Total MOps: %.3lf\n",<o:p></o:p></p>
<p class="MsoPlainText">> bandwidth_total, mops_total);<o:p></o:p></p>
<p class="MsoPlainText">> +         snprintf(output_str[MAX_WORKER_NB], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> CSV_TOTAL_LINE_FMT,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      cfg->scenario_id, nr_buf, memory * nb_workers,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      avg_cycles_total / nb_workers, bandwidth_total,<o:p></o:p></p>
<p class="MsoPlainText">> mops_total);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +out:<o:p></o:p></p>
<p class="MsoPlainText">> +         /* free mbufs used in the test */<o:p></o:p></p>
<p class="MsoPlainText">> +         if (srcs != NULL)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_pktmbuf_free_bulk(srcs, nr_buf);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (dsts != NULL)<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_pktmbuf_free_bulk(dsts, nr_buf);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         /* free the points for the mbufs */<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_free(srcs);<o:p></o:p></p>
<p class="MsoPlainText">> +         srcs = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_free(dsts);<o:p></o:p></p>
<p class="MsoPlainText">> +         dsts = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_mempool_free(src_pool);<o:p></o:p></p>
<p class="MsoPlainText">> +         src_pool = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_mempool_free(dst_pool);<o:p></o:p></p>
<p class="MsoPlainText">> +         dst_pool = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         /* free the worker parameters */<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_workers; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       rte_free(lcores[i]);<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcores[i] = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (is_dma) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (i = 0; i < nb_workers; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Stopping dmadev %d\n", ldm->dma_ids[i]);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rte_dma_stop(ldm->dma_ids[i]);<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/test-dma-perf/config.ini <o:p></o:p></p>
<p class="MsoPlainText">> b/app/test-dma-perf/config.ini new file mode 100644 index
<o:p></o:p></p>
<p class="MsoPlainText">> 0000000000..b550f4b23f<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/test-dma-perf/config.ini<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,61 @@<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; This is an example configuration file for dma-perf, which details
<o:p></o:p></p>
<p class="MsoPlainText">> +the meanings of each parameter ; and instructions on how to use dma-perf.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; Supported test types are DMA_MEM_COPY and CPU_MEM_COPY.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; Parameters:<o:p></o:p></p>
<p class="MsoPlainText">> +; "mem_size" denotes the size of the memory footprint.<o:p></o:p></p>
<p class="MsoPlainText">> +; "buf_size" denotes the memory size of a single operation.<o:p></o:p></p>
<p class="MsoPlainText">> +; "dma_ring_size" denotes the dma ring buffer size. It should be must
<o:p></o:p></p>
<p class="MsoPlainText">> +be a power of two, and between ;  64 and 4096.<o:p></o:p></p>
<p class="MsoPlainText">> +; "kick_batch" denotes the dma operation batch size, and should be
<o:p></o:p></p>
<p class="MsoPlainText">> +greater<o:p></o:p></p>
<p class="MsoPlainText">> than 1 normally.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; The format for variables is variable=first,last,increment,ADD|MUL.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; src_numa_node is used to control the numa node where the source<o:p></o:p></p>
<p class="MsoPlainText">> memory is allocated.<o:p></o:p></p>
<p class="MsoPlainText">> +; dst_numa_node is used to control the numa node where the
<o:p></o:p></p>
<p class="MsoPlainText">> +destination<o:p></o:p></p>
<p class="MsoPlainText">> memory is allocated.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; cache_flush is used to determine whether or not the cache should be
<o:p></o:p></p>
<p class="MsoPlainText">> +flushed, with 1 indicating to ; flush and 0 indicating to not flush.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; test_seconds controls the test time of the whole case.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; To use DMA for a test, please specify the "lcore_dma" parameter.<o:p></o:p></p>
<p class="MsoPlainText">> +; If you have already set the "-l" and "-a" parameters using EAL, ;
<o:p></o:p></p>
<p class="MsoPlainText">> +make sure that the value of "lcore_dma" falls within their range of
<o:p></o:p></p>
<p class="MsoPlainText">> +the<o:p></o:p></p>
<p class="MsoPlainText">> values.<o:p></o:p></p>
<p class="MsoPlainText">> +; We have to ensure a 1:1 mapping between the core and DMA device.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; To use CPU for a test, please specify the "lcore" parameter.<o:p></o:p></p>
<p class="MsoPlainText">> +; If you have already set the "-l" and "-a" parameters using EAL, ;
<o:p></o:p></p>
<p class="MsoPlainText">> +make sure that the value of "lcore" falls within their range of values.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; To specify a configuration file, use the "--config" flag followed
<o:p></o:p></p>
<p class="MsoPlainText">> +by the path<o:p></o:p></p>
<p class="MsoPlainText">> to the file.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +; To specify a result file, use the "--result" flag followed by the
<o:p></o:p></p>
<p class="MsoPlainText">> +path to the<o:p></o:p></p>
<p class="MsoPlainText">> file.<o:p></o:p></p>
<p class="MsoPlainText">> +; If you do not specify a result file, one will be generated with the
<o:p></o:p></p>
<p class="MsoPlainText">> +same name as the configuration ; file, with the addition of
<o:p></o:p></p>
<p class="MsoPlainText">> +"_result.csv" at<o:p></o:p></p>
<p class="MsoPlainText">> the end.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +[case1]<o:p></o:p></p>
<p class="MsoPlainText">> +type=DMA_MEM_COPY<o:p></o:p></p>
<p class="MsoPlainText">> +mem_size=10<o:p></o:p></p>
<p class="MsoPlainText">> +buf_size=64,8192,2,MUL<o:p></o:p></p>
<p class="MsoPlainText">> +dma_ring_size=1024<o:p></o:p></p>
<p class="MsoPlainText">> +kick_batch=32<o:p></o:p></p>
<p class="MsoPlainText">> +src_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +dst_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +cache_flush=0<o:p></o:p></p>
<p class="MsoPlainText">> +test_seconds=2<o:p></o:p></p>
<p class="MsoPlainText">> <a href="mailto:+lcore_dma=lcore10@0000:00:04.2">+lcore_dma=lcore10@0000:00:04.2</a>,
<a href="mailto:lcore11@0000:00:04.3">lcore11@0000:00:04.3</a> <o:p></o:p></p>
<p class="MsoPlainText">> +eal_args=--in-memory --file-prefix=test<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +[case2]<o:p></o:p></p>
<p class="MsoPlainText">> +type=CPU_MEM_COPY<o:p></o:p></p>
<p class="MsoPlainText">> +mem_size=10<o:p></o:p></p>
<p class="MsoPlainText">> +buf_size=64,8192,2,MUL<o:p></o:p></p>
<p class="MsoPlainText">> +src_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +dst_numa_node=1<o:p></o:p></p>
<p class="MsoPlainText">> +cache_flush=0<o:p></o:p></p>
<p class="MsoPlainText">> +test_seconds=2<o:p></o:p></p>
<p class="MsoPlainText">> +lcore = 3, 4<o:p></o:p></p>
<p class="MsoPlainText">> +eal_args=--in-memory --no-pci<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/test-dma-perf/main.c b/app/test-dma-perf/main.c new
<o:p></o:p></p>
<p class="MsoPlainText">> file mode 100644 index 0000000000..de37120df6<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/test-dma-perf/main.c<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,616 @@<o:p></o:p></p>
<p class="MsoPlainText">> +/* SPDX-License-Identifier: BSD-3-Clause<o:p></o:p></p>
<p class="MsoPlainText">> + * Copyright(c) 2023 Intel Corporation  */<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include <stdio.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <stdlib.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <getopt.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <signal.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <stdbool.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <unistd.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <sys/wait.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <inttypes.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <libgen.h><o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_eal.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_cfgfile.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_string_fns.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_lcore.h><o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include "main.h"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define CSV_HDR_FMT "Case %u : %s,lcore,DMA,DMA ring size,kick batch<o:p></o:p></p>
<p class="MsoPlainText">> size,buffer size(B),number of buffers,memory(MB),average
<o:p></o:p></p>
<p class="MsoPlainText">> cycle,bandwidth(Gbps),MOps\n"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_EAL_PARAM_NB 100<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_EAL_PARAM_LEN 1024<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define DMA_MEM_COPY "DMA_MEM_COPY"<o:p></o:p></p>
<p class="MsoPlainText">> +#define CPU_MEM_COPY "CPU_MEM_COPY"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define CMDLINE_CONFIG_ARG "--config"<o:p></o:p></p>
<p class="MsoPlainText">> +#define CMDLINE_RESULT_ARG "--result"<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_PARAMS_PER_ENTRY 4<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_LONG_OPT_SZ 64<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +enum {<o:p></o:p></p>
<p class="MsoPlainText">> +         TEST_TYPE_NONE = 0,<o:p></o:p></p>
<p class="MsoPlainText">> +         TEST_TYPE_DMA_MEM_COPY,<o:p></o:p></p>
<p class="MsoPlainText">> +         TEST_TYPE_CPU_MEM_COPY<o:p></o:p></p>
<p class="MsoPlainText">> +};<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_TEST_CASES 16<o:p></o:p></p>
<p class="MsoPlainText">> +static struct test_configure test_cases[MAX_TEST_CASES];<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +char output_str[MAX_WORKER_NB + 1][MAX_OUTPUT_STR_LEN];<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static FILE *fd;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +output_csv(bool need_blankline)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (need_blankline) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       fprintf(fd, ",,,,,,,,\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       fprintf(fd, ",,,,,,,,\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < RTE_DIM(output_str); i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (output_str[i][0]) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(fd, "%s", output_str[i]);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      output_str[i][0] = '\0';<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         fflush(fd);<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +output_env_info(void)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         snprintf(output_str[0], MAX_OUTPUT_STR_LEN, "Test<o:p></o:p></p>
<p class="MsoPlainText">> Environment:\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         snprintf(output_str[1], MAX_OUTPUT_STR_LEN, "CPU<o:p></o:p></p>
<p class="MsoPlainText">> frequency,%.3lf Ghz",<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rte_get_timer_hz() / 1000000000.0);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         output_csv(true);<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +output_header(uint32_t case_id, struct test_configure *case_cfg) {<o:p></o:p></p>
<p class="MsoPlainText">> +         snprintf(output_str[0], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> +                                      CSV_HDR_FMT, case_id, case_cfg->test_type_str);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         output_csv(true);<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +run_test_case(struct test_configure *case_cfg) {<o:p></o:p></p>
<p class="MsoPlainText">> +         switch (case_cfg->test_type) {<o:p></o:p></p>
<p class="MsoPlainText">> +         case TEST_TYPE_DMA_MEM_COPY:<o:p></o:p></p>
<p class="MsoPlainText">> +                       mem_copy_benchmark(case_cfg, true);<o:p></o:p></p>
<p class="MsoPlainText">> +                       break;<o:p></o:p></p>
<p class="MsoPlainText">> +         case TEST_TYPE_CPU_MEM_COPY:<o:p></o:p></p>
<p class="MsoPlainText">> +                       mem_copy_benchmark(case_cfg, false);<o:p></o:p></p>
<p class="MsoPlainText">> +                       break;<o:p></o:p></p>
<p class="MsoPlainText">> +         default:<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Unknown test type. %s\n", case_cfg->test_type_str);<o:p></o:p></p>
<p class="MsoPlainText">> +                       break;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static void<o:p></o:p></p>
<p class="MsoPlainText">> +run_test(uint32_t case_id, struct test_configure *case_cfg) {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nb_lcores = rte_lcore_count();<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry *mem_size = &case_cfg->mem_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry *buf_size = &case_cfg->buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry *ring_size = &case_cfg->ring_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry *kick_batch = &case_cfg->kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry dummy = { 0 };<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry *var_entry = &dummy;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < RTE_DIM(output_str); i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       memset(output_str[i], 0, MAX_OUTPUT_STR_LEN);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (nb_lcores <= case_cfg->lcore_dma_map.cnt) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Case %u: Not enough lcores.\n", case_id);<o:p></o:p></p>
<p class="MsoPlainText">> +                       return;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Number of used lcores: %u.\n", nb_lcores);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (mem_size->incr != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       var_entry = mem_size;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (buf_size->incr != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       var_entry = buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (ring_size->incr != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       var_entry = ring_size;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (kick_batch->incr != 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                       var_entry = kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         case_cfg->scenario_id = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         output_header(case_id, case_cfg);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (var_entry->cur = var_entry->first; var_entry->cur <= var_entry-<o:p></o:p></p>
<p class="MsoPlainText">> >last;) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       case_cfg->scenario_id++;<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("\nRunning scenario %d\n", case_cfg->scenario_id);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       run_test_case(case_cfg);<o:p></o:p></p>
<p class="MsoPlainText">> +                       output_csv(false);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (var_entry->op == OP_ADD)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      var_entry->cur += var_entry->incr;<o:p></o:p></p>
<p class="MsoPlainText">> +                       else if (var_entry->op == OP_MUL)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      var_entry->cur *= var_entry->incr;<o:p></o:p></p>
<p class="MsoPlainText">> +                       else {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("No proper operation for variable entry.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static int<o:p></o:p></p>
<p class="MsoPlainText">> +parse_lcore(struct test_configure *test_case, const char *value) {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t len;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *input;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_dma_map_t *lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (test_case == NULL || value == NULL)<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         len = strlen(value);<o:p></o:p></p>
<p class="MsoPlainText">> +         input = (char *)malloc((len + 1) * sizeof(char));<o:p></o:p></p>
<p class="MsoPlainText">> +         strlcpy(input, value, len + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +         lcore_dma_map = &(test_case->lcore_dma_map);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         memset(lcore_dma_map, 0, sizeof(struct lcore_dma_map_t));<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         char *token = strtok(input, ", ");<o:p></o:p></p>
<p class="MsoPlainText">> +         while (token != NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (lcore_dma_map->cnt >= MAX_LCORE_NB) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      free(input);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       uint16_t lcore_id = atoi(token);<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_dma_map->lcores[lcore_dma_map->cnt++] = lcore_id;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       token = strtok(NULL, ", ");<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         free(input);<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static int<o:p></o:p></p>
<p class="MsoPlainText">> +parse_lcore_dma(struct test_configure *test_case, const char *value) {<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_dma_map_t *lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *input, *addrs;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *ptrs[2];<o:p></o:p></p>
<p class="MsoPlainText">> +         char *start, *end, *substr;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t lcore_id;<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (test_case == NULL || value == NULL)<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         input = strndup(value, strlen(value) + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +         addrs = input;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         while (*addrs == '\0')<o:p></o:p></p>
<p class="MsoPlainText">> +                       addrs++;<o:p></o:p></p>
<p class="MsoPlainText">> +         if (*addrs == '\0') {<o:p></o:p></p>
<p class="MsoPlainText">> +                       fprintf(stderr, "No input DMA addresses\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         substr = strtok(addrs, ",");<o:p></o:p></p>
<p class="MsoPlainText">> +         if (substr == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       fprintf(stderr, "No input DMA address\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         memset(&test_case->lcore_dma_map, 0, sizeof(struct<o:p></o:p></p>
<p class="MsoPlainText">> lcore_dma_map_t));<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         do {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (rte_strsplit(substr, strlen(substr), ptrs, 2, '@') < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(stderr, "Illegal DMA address\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       start = strstr(ptrs[0], "lcore");<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (start == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(stderr, "Illegal lcore\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       start += 5;<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_id = strtol(start, &end, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (end == start) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(stderr, "No input lcore ID or ID %d is wrong\n",<o:p></o:p></p>
<p class="MsoPlainText">> lcore_id);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_dma_map = &test_case->lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (lcore_dma_map->cnt >= MAX_LCORE_NB) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fprintf(stderr, "lcores count error\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      break;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_dma_map->lcores[lcore_dma_map->cnt] = lcore_id;<o:p></o:p></p>
<p class="MsoPlainText">> +                       strlcpy(lcore_dma_map->dma_names[lcore_dma_map->cnt],<o:p></o:p></p>
<p class="MsoPlainText">> ptrs[1],<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    RTE_DEV_NAME_MAX_LEN);<o:p></o:p></p>
<p class="MsoPlainText">> +                       lcore_dma_map->cnt++;<o:p></o:p></p>
<p class="MsoPlainText">> +                       substr = strtok(NULL, ",");<o:p></o:p></p>
<p class="MsoPlainText">> +         } while (substr != NULL);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +out:<o:p></o:p></p>
<p class="MsoPlainText">> +         free(input);<o:p></o:p></p>
<p class="MsoPlainText">> +         return ret;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static int<o:p></o:p></p>
<p class="MsoPlainText">> +parse_entry(const char *value, struct test_configure_entry *entry) {<o:p></o:p></p>
<p class="MsoPlainText">> +         char input[255] = {0};<o:p></o:p></p>
<p class="MsoPlainText">> +         char *args[MAX_PARAMS_PER_ENTRY];<o:p></o:p></p>
<p class="MsoPlainText">> +         int args_nr = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (value == NULL || entry == NULL)<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         strncpy(input, value, 254);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (*input == '\0')<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         ret = rte_strsplit(input, strlen(input), args, MAX_PARAMS_PER_ENTRY,<o:p></o:p></p>
<p class="MsoPlainText">> ',');<o:p></o:p></p>
<p class="MsoPlainText">> +         if (ret != 1 && ret != 4)<o:p></o:p></p>
<p class="MsoPlainText">> +                       goto out;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         entry->cur = entry->first = (uint32_t)atoi(args[0]);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (ret == 4) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       args_nr = 4;<o:p></o:p></p>
<p class="MsoPlainText">> +                       entry->last = (uint32_t)atoi(args[1]);<o:p></o:p></p>
<p class="MsoPlainText">> +                       entry->incr = (uint32_t)atoi(args[2]);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (!strcmp(args[3], "MUL"))<o:p></o:p></p>
<p class="MsoPlainText">> +                                      entry->op = OP_MUL;<o:p></o:p></p>
<p class="MsoPlainText">> +                       else if (!strcmp(args[3], "ADD"))<o:p></o:p></p>
<p class="MsoPlainText">> +                                      entry->op = OP_ADD;<o:p></o:p></p>
<p class="MsoPlainText">> +                       else {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      args_nr = -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Invalid op %s.\n", args[3]);<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         } else {<o:p></o:p></p>
<p class="MsoPlainText">> +                       args_nr = 1;<o:p></o:p></p>
<p class="MsoPlainText">> +                       entry->op = OP_NONE;<o:p></o:p></p>
<p class="MsoPlainText">> +                       entry->last = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                       entry->incr = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +out:<o:p></o:p></p>
<p class="MsoPlainText">> +         return args_nr;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +static uint16_t<o:p></o:p></p>
<p class="MsoPlainText">> +load_configs(const char *path)<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         struct rte_cfgfile *cfgfile;<o:p></o:p></p>
<p class="MsoPlainText">> +         int nb_sections, i;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure *test_case;<o:p></o:p></p>
<p class="MsoPlainText">> +         char section_name[CFG_NAME_LEN];<o:p></o:p></p>
<p class="MsoPlainText">> +         const char *case_type;<o:p></o:p></p>
<p class="MsoPlainText">> +         const char *lcore_dma;<o:p></o:p></p>
<p class="MsoPlainText">> +         const char *mem_size_str, *buf_size_str, *ring_size_str,<o:p></o:p></p>
<p class="MsoPlainText">> *kick_batch_str;<o:p></o:p></p>
<p class="MsoPlainText">> +         int args_nr, nb_vp;<o:p></o:p></p>
<p class="MsoPlainText">> +         bool is_dma;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("config file parsing...\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         cfgfile = rte_cfgfile_load(path, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (!cfgfile) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Open configure file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       exit(1);<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         nb_sections = rte_cfgfile_num_sections(cfgfile, NULL, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +         if (nb_sections > MAX_TEST_CASES) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Error: The maximum number of cases is %d.\n",<o:p></o:p></p>
<p class="MsoPlainText">> MAX_TEST_CASES);<o:p></o:p></p>
<p class="MsoPlainText">> +                       exit(1);<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < nb_sections; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       snprintf(section_name, CFG_NAME_LEN, "case%d", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case = &test_cases[i];<o:p></o:p></p>
<p class="MsoPlainText">> +                       case_type = rte_cfgfile_get_entry(cfgfile, section_name,<o:p></o:p></p>
<p class="MsoPlainText">> "type");<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (case_type == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Error: No case type in case %d, the test will be<o:p></o:p></p>
<p class="MsoPlainText">> finished here.\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (strcmp(case_type, DMA_MEM_COPY) == 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->test_type = TEST_TYPE_DMA_MEM_COPY;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->test_type_str = DMA_MEM_COPY;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      is_dma = true;<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else if (strcmp(case_type, CPU_MEM_COPY) == 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->test_type = TEST_TYPE_CPU_MEM_COPY;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->test_type_str = CPU_MEM_COPY;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      is_dma = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Error: Wrong test case type %s in case%d.\n",<o:p></o:p></p>
<p class="MsoPlainText">> case_type, i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->src_numa_node =<o:p></o:p></p>
<p class="MsoPlainText">> (int)atoi(rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                                                             section_name,<o:p></o:p></p>
<p class="MsoPlainText">> "src_numa_node"));<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->dst_numa_node =<o:p></o:p></p>
<p class="MsoPlainText">> (int)atoi(rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                                                             section_name,<o:p></o:p></p>
<p class="MsoPlainText">> "dst_numa_node"));<o:p></o:p></p>
<p class="MsoPlainText">> +                       nb_vp = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                       mem_size_str = rte_cfgfile_get_entry(cfgfile, section_name,<o:p></o:p></p>
<p class="MsoPlainText">> "mem_size");<o:p></o:p></p>
<p class="MsoPlainText">> +                       args_nr = parse_entry(mem_size_str, &test_case-<o:p></o:p></p>
<p class="MsoPlainText">> >mem_size);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (args_nr < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("parse error in case %d.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else if (args_nr == 4)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nb_vp++;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       buf_size_str = rte_cfgfile_get_entry(cfgfile, section_name,<o:p></o:p></p>
<p class="MsoPlainText">> "buf_size");<o:p></o:p></p>
<p class="MsoPlainText">> +                       args_nr = parse_entry(buf_size_str, &test_case->buf_size);<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (args_nr < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("parse error in case %d.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else if (args_nr == 4)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nb_vp++;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (is_dma) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ring_size_str = rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name,<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">>            "dma_ring_size");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      args_nr = parse_entry(ring_size_str, &test_case-<o:p></o:p></p>
<p class="MsoPlainText">> >ring_size);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (args_nr < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("parse error in case %d.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      } else if (args_nr == 4)<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    nb_vp++;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      kick_batch_str = rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name, "kick_batch");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      args_nr = parse_entry(kick_batch_str, &test_case-<o:p></o:p></p>
<p class="MsoPlainText">> >kick_batch);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (args_nr < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("parse error in case %d.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      } else if (args_nr == 4)<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    nb_vp++;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      lcore_dma = rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name, "lcore_dma");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      int lcore_ret = parse_lcore_dma(test_case,<o:p></o:p></p>
<p class="MsoPlainText">> lcore_dma);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (lcore_ret < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("parse lcore dma error in case %d.\n",<o:p></o:p></p>
<p class="MsoPlainText">> i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      lcore_dma = rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name, "lcore");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      int lcore_ret = parse_lcore(test_case, lcore_dma);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (lcore_ret < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("parse lcore error in case %d.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (nb_vp > 1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Case %d error, each section can only have a<o:p></o:p></p>
<p class="MsoPlainText">> single variable parameter.\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      test_case->is_valid = false;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->cache_flush =<o:p></o:p></p>
<p class="MsoPlainText">> +                                      (uint8_t)atoi(rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name, "cache_flush"));<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->test_secs =<o:p></o:p></p>
<p class="MsoPlainText">> (uint16_t)atoi(rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   section_name, "test_seconds"));<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->eal_args = rte_cfgfile_get_entry(cfgfile,<o:p></o:p></p>
<p class="MsoPlainText">> section_name, "eal_args");<o:p></o:p></p>
<p class="MsoPlainText">> +                       test_case->is_valid = true;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         rte_cfgfile_close(cfgfile);<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("config file parsing complete.\n\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         return i;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +/* Parse the argument given in the command line of the application */
<o:p></o:p></p>
<p class="MsoPlainText">> +static int append_eal_args(int argc, char **argv, const char
<o:p></o:p></p>
<p class="MsoPlainText">> +*eal_args, char **new_argv) {<o:p></o:p></p>
<p class="MsoPlainText">> +         int i;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *tokens[MAX_EAL_PARAM_NB];<o:p></o:p></p>
<p class="MsoPlainText">> +         char args[MAX_EAL_PARAM_LEN] = {0};<o:p></o:p></p>
<p class="MsoPlainText">> +         int token_nb, new_argc = 0;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < argc; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if ((strcmp(argv[i], CMDLINE_CONFIG_ARG) == 0) ||<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    (strcmp(argv[i], CMDLINE_RESULT_ARG) == 0))<o:p></o:p></p>
<p class="MsoPlainText">> {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      i++;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       strlcpy(new_argv[new_argc], argv[i], MAX_EAL_PARAM_LEN);<o:p></o:p></p>
<p class="MsoPlainText">> +                       new_argc++;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         if (eal_args) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       strlcpy(args, eal_args, MAX_EAL_PARAM_LEN);<o:p></o:p></p>
<p class="MsoPlainText">> +                       token_nb = rte_strsplit(args, strlen(args),<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   tokens, MAX_EAL_PARAM_NB, ' ');<o:p></o:p></p>
<p class="MsoPlainText">> +                       for (i = 0; i < token_nb; i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      strlcpy(new_argv[new_argc++], tokens[i],<o:p></o:p></p>
<p class="MsoPlainText">> MAX_EAL_PARAM_LEN);<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         return new_argc;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +int<o:p></o:p></p>
<p class="MsoPlainText">> +main(int argc, char *argv[])<o:p></o:p></p>
<p class="MsoPlainText">> +{<o:p></o:p></p>
<p class="MsoPlainText">> +         int ret;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t case_nb;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t i, nb_lcores;<o:p></o:p></p>
<p class="MsoPlainText">> +         pid_t cpid, wpid;<o:p></o:p></p>
<p class="MsoPlainText">> +         int wstatus;<o:p></o:p></p>
<p class="MsoPlainText">> +         char args[MAX_EAL_PARAM_NB][MAX_EAL_PARAM_LEN];<o:p></o:p></p>
<p class="MsoPlainText">> +         char *pargs[MAX_EAL_PARAM_NB];<o:p></o:p></p>
<p class="MsoPlainText">> +         char *cfg_path_ptr = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +         char *rst_path_ptr = NULL;<o:p></o:p></p>
<p class="MsoPlainText">> +         char rst_path[PATH_MAX];<o:p></o:p></p>
<p class="MsoPlainText">> +         int new_argc;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         memset(args, 0, sizeof(args));<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < RTE_DIM(pargs); i++)<o:p></o:p></p>
<p class="MsoPlainText">> +                       pargs[i] = args[i];<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < (uint32_t)argc; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (strncmp(argv[i], CMDLINE_CONFIG_ARG,<o:p></o:p></p>
<p class="MsoPlainText">> MAX_LONG_OPT_SZ) == 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      cfg_path_ptr = argv[i + 1];<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (strncmp(argv[i], CMDLINE_RESULT_ARG,<o:p></o:p></p>
<p class="MsoPlainText">> MAX_LONG_OPT_SZ) == 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                                      rst_path_ptr = argv[i + 1];<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +         if (cfg_path_ptr == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Config file not assigned.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +         if (rst_path_ptr == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       strlcpy(rst_path, cfg_path_ptr, PATH_MAX);<o:p></o:p></p>
<p class="MsoPlainText">> +                       char *token = strtok(basename(rst_path), ".");<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (token == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Config file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +                       strcat(token, "_result.csv");<o:p></o:p></p>
<p class="MsoPlainText">> +                       rst_path_ptr = rst_path;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         case_nb = load_configs(cfg_path_ptr);<o:p></o:p></p>
<p class="MsoPlainText">> +         fd = fopen(rst_path_ptr, "w");<o:p></o:p></p>
<p class="MsoPlainText">> +         if (fd == NULL) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       printf("Open output CSV file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       return -1;<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +         fclose(fd);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Running cases...\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         for (i = 0; i < case_nb; i++) {<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (!test_cases[i].is_valid) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Invalid test case %d.\n\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      snprintf(output_str[0], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> "Invalid case %d\n", i +<o:p></o:p></p>
<p class="MsoPlainText">> +1);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fd = fopen(rst_path_ptr, "a");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (!fd) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Open output CSV file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                                      output_csv(true);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fclose(fd);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (test_cases[i].test_type == TEST_TYPE_NONE) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("No valid test type in test case %d.\n\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      snprintf(output_str[0], MAX_OUTPUT_STR_LEN,<o:p></o:p></p>
<p class="MsoPlainText">> "Invalid case %d\n", i +<o:p></o:p></p>
<p class="MsoPlainText">> +1);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fd = fopen(rst_path_ptr, "a");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (!fd) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Open output CSV file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +                                      output_csv(true);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fclose(fd);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      continue;<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                       cpid = fork();<o:p></o:p></p>
<p class="MsoPlainText">> +                       if (cpid < 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("Fork case %d failed.\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      exit(EXIT_FAILURE);<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else if (cpid == 0) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("\nRunning case %u\n\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      new_argc = append_eal_args(argc, argv,<o:p></o:p></p>
<p class="MsoPlainText">> test_cases[i].eal_args, pargs);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      ret = rte_eal_init(new_argc, pargs);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (ret < 0)<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    rte_exit(EXIT_FAILURE, "Invalid EAL<o:p></o:p></p>
<p class="MsoPlainText">> arguments\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      /* Check lcores. */<o:p></o:p></p>
<p class="MsoPlainText">> +                                      nb_lcores = rte_lcore_count();<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (nb_lcores < 2)<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    rte_exit(EXIT_FAILURE,<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   "There should be at least 2 worker<o:p></o:p></p>
<p class="MsoPlainText">> lcores.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fd = fopen(rst_path_ptr, "a");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (!fd) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Open output CSV file error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      output_env_info();<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      run_test(i + 1, &test_cases[i]);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      /* clean up the EAL */<o:p></o:p></p>
<p class="MsoPlainText">> +                                     rte_eal_cleanup();<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      fclose(fd);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      printf("\nCase %u completed.\n\n", i + 1);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      exit(EXIT_SUCCESS);<o:p></o:p></p>
<p class="MsoPlainText">> +                       } else {<o:p></o:p></p>
<p class="MsoPlainText">> +                                      wpid = waitpid(cpid, &wstatus, 0);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (wpid == -1) {<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("waitpid error.\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    exit(EXIT_FAILURE);<o:p></o:p></p>
<p class="MsoPlainText">> +                                      }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +                                      if (WIFEXITED(wstatus))<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Case process exited. status %d\n\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   WEXITSTATUS(wstatus));<o:p></o:p></p>
<p class="MsoPlainText">> +                                      else if (WIFSIGNALED(wstatus))<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Case process killed by signal %d\n\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   WTERMSIG(wstatus));<o:p></o:p></p>
<p class="MsoPlainText">> +                                      else if (WIFSTOPPED(wstatus))<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Case process stopped by<o:p></o:p></p>
<p class="MsoPlainText">> signal %d\n\n",<o:p></o:p></p>
<p class="MsoPlainText">> +                                                                   WSTOPSIG(wstatus));<o:p></o:p></p>
<p class="MsoPlainText">> +                                      else if (WIFCONTINUED(wstatus))<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Case process continued.\n\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                                      else<o:p></o:p></p>
<p class="MsoPlainText">> +                                                    printf("Case process unknown<o:p></o:p></p>
<p class="MsoPlainText">> terminated.\n\n");<o:p></o:p></p>
<p class="MsoPlainText">> +                       }<o:p></o:p></p>
<p class="MsoPlainText">> +         }<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         printf("Bye...\n");<o:p></o:p></p>
<p class="MsoPlainText">> +         return 0;<o:p></o:p></p>
<p class="MsoPlainText">> +}<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/test-dma-perf/main.h b/app/test-dma-perf/main.h new
<o:p></o:p></p>
<p class="MsoPlainText">> file mode 100644 index 0000000000..12bc3f4e3f<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/test-dma-perf/main.h<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,64 @@<o:p></o:p></p>
<p class="MsoPlainText">> +/* SPDX-License-Identifier: BSD-3-Clause<o:p></o:p></p>
<p class="MsoPlainText">> + * Copyright(c) 2023 Intel Corporation  */<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#ifndef _MAIN_H_<o:p></o:p></p>
<p class="MsoPlainText">> +#define _MAIN_H_<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_common.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_cycles.h><o:p></o:p></p>
<p class="MsoPlainText">> +#include <rte_dev.h><o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_WORKER_NB 128<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_OUTPUT_STR_LEN 512<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_DMA_NB 128<o:p></o:p></p>
<p class="MsoPlainText">> +#define MAX_LCORE_NB 256<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +extern char output_str[MAX_WORKER_NB + 1][MAX_OUTPUT_STR_LEN];<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +typedef enum {<o:p></o:p></p>
<p class="MsoPlainText">> +         OP_NONE = 0,<o:p></o:p></p>
<p class="MsoPlainText">> +         OP_ADD,<o:p></o:p></p>
<p class="MsoPlainText">> +         OP_MUL<o:p></o:p></p>
<p class="MsoPlainText">> +} alg_op_type;<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +struct test_configure_entry {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t first;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t last;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t incr;<o:p></o:p></p>
<p class="MsoPlainText">> +         alg_op_type op;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t cur;<o:p></o:p></p>
<p class="MsoPlainText">> +};<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +struct lcore_dma_map_t {<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t lcores[MAX_WORKER_NB];<o:p></o:p></p>
<p class="MsoPlainText">> +         char dma_names[MAX_WORKER_NB][RTE_DEV_NAME_MAX_LEN];<o:p></o:p></p>
<p class="MsoPlainText">> +         int16_t dma_ids[MAX_WORKER_NB];<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t cnt;<o:p></o:p></p>
<p class="MsoPlainText">> +};<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +struct test_configure {<o:p></o:p></p>
<p class="MsoPlainText">> +         bool is_valid;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint8_t test_type;<o:p></o:p></p>
<p class="MsoPlainText">> +         const char *test_type_str;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t src_numa_node;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t dst_numa_node;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t opcode;<o:p></o:p></p>
<p class="MsoPlainText">> +         bool is_dma;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct lcore_dma_map_t lcore_dma_map;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry mem_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry buf_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry ring_size;<o:p></o:p></p>
<p class="MsoPlainText">> +         struct test_configure_entry kick_batch;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint8_t cache_flush;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint32_t nr_buf;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint16_t test_secs;<o:p></o:p></p>
<p class="MsoPlainText">> +         const char *eal_args;<o:p></o:p></p>
<p class="MsoPlainText">> +         uint8_t scenario_id;<o:p></o:p></p>
<p class="MsoPlainText">> +};<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +void mem_copy_benchmark(struct test_configure *cfg, bool is_dma);<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +#endif /* _MAIN_H_ */<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/app/test-dma-perf/meson.build b/app/test-dma-
<o:p></o:p></p>
<p class="MsoPlainText">> perf/meson.build new file mode 100644 index 0000000000..bd6c264002<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/app/test-dma-perf/meson.build<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,17 @@<o:p></o:p></p>
<p class="MsoPlainText">> +# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2019-2023
<o:p></o:p></p>
<p class="MsoPlainText">> +Intel Corporation<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +# meson file, for building this app as part of a main DPDK build.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +if is_windows<o:p></o:p></p>
<p class="MsoPlainText">> +    build = false<o:p></o:p></p>
<p class="MsoPlainText">> +    reason = 'not supported on Windows'<o:p></o:p></p>
<p class="MsoPlainText">> +    subdir_done()<o:p></o:p></p>
<p class="MsoPlainText">> +endif<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +deps += ['dmadev', 'mbuf', 'cfgfile']<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +sources = files(<o:p></o:p></p>
<p class="MsoPlainText">> +        'main.c',<o:p></o:p></p>
<p class="MsoPlainText">> +        'benchmark.c',<o:p></o:p></p>
<p class="MsoPlainText">> +)<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/doc/guides/rel_notes/release_23_07.rst<o:p></o:p></p>
<p class="MsoPlainText">> b/doc/guides/rel_notes/release_23_07.rst<o:p></o:p></p>
<p class="MsoPlainText">> index 4459144140..796cc5517d 100644<o:p></o:p></p>
<p class="MsoPlainText">> --- a/doc/guides/rel_notes/release_23_07.rst<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/doc/guides/rel_notes/release_23_07.rst<o:p></o:p></p>
<p class="MsoPlainText">> @@ -200,6 +200,12 @@ New Features<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">>    Enhanced the GRO library to support TCP packets over IPv6 network.<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> +* **Added DMA device performance test application.**<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +  Added an new application to test the performance of DMA device and CPU.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +  See the :doc:`../tools/dmaperf` for more details.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">>  Removed Items<o:p></o:p></p>
<p class="MsoPlainText">>  -------------<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/doc/guides/tools/dmaperf.rst <o:p></o:p></p>
<p class="MsoPlainText">> b/doc/guides/tools/dmaperf.rst new file mode 100644 index
<o:p></o:p></p>
<p class="MsoPlainText">> 0000000000..c5f8a9406f<o:p></o:p></p>
<p class="MsoPlainText">> --- /dev/null<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/doc/guides/tools/dmaperf.rst<o:p></o:p></p>
<p class="MsoPlainText">> @@ -0,0 +1,103 @@<o:p></o:p></p>
<p class="MsoPlainText">> +..  SPDX-License-Identifier: BSD-3-Clause<o:p></o:p></p>
<p class="MsoPlainText">> +    Copyright(c) 2023 Intel Corporation.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +dpdk-test-dma-perf Application<o:p></o:p></p>
<p class="MsoPlainText">> +==============================<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +The ``dpdk-test-dma-perf`` tool is a Data Plane Development Kit
<o:p></o:p></p>
<p class="MsoPlainText">> +(DPDK) application that enables testing the performance of DMA
<o:p></o:p></p>
<p class="MsoPlainText">> +(Direct Memory<o:p></o:p></p>
<p class="MsoPlainText">> +Access) devices available within DPDK. It provides a test framework
<o:p></o:p></p>
<p class="MsoPlainText">> +to assess the performance of CPU and DMA devices under various
<o:p></o:p></p>
<p class="MsoPlainText">> +scenarios, such as varying buffer lengths. Doing so provides insight
<o:p></o:p></p>
<p class="MsoPlainText">> +into the potential performance when using these DMA devices for
<o:p></o:p></p>
<p class="MsoPlainText">> +acceleration in DPDK applications. It supports memory copy
<o:p></o:p></p>
<p class="MsoPlainText">> +performance tests for now,<o:p></o:p></p>
<p class="MsoPlainText">> comparing the performance of CPU and DMA automatically in various
<o:p></o:p></p>
<p class="MsoPlainText">> conditions with the help of a pre-set configuration file.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Configuration<o:p></o:p></p>
<p class="MsoPlainText">> +-------------<o:p></o:p></p>
<p class="MsoPlainText">> +This application uses inherent DPDK EAL command-line options as well
<o:p></o:p></p>
<p class="MsoPlainText">> +as custom command-line options in the application. An example
<o:p></o:p></p>
<p class="MsoPlainText">> +configuration file for the application is provided and gives the
<o:p></o:p></p>
<p class="MsoPlainText">> +meanings for<o:p></o:p></p>
<p class="MsoPlainText">> each parameter.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Here is an extracted sample from the configuration file (the complete
<o:p></o:p></p>
<p class="MsoPlainText">> +sample can be found in the application source directory):<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +.. code-block:: ini<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +   [case1]<o:p></o:p></p>
<p class="MsoPlainText">> +   type=DMA_MEM_COPY<o:p></o:p></p>
<p class="MsoPlainText">> +   mem_size=10<o:p></o:p></p>
<p class="MsoPlainText">> +   buf_size=64,8192,2,MUL<o:p></o:p></p>
<p class="MsoPlainText">> +   dma_ring_size=1024<o:p></o:p></p>
<p class="MsoPlainText">> +   kick_batch=32<o:p></o:p></p>
<p class="MsoPlainText">> +   src_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +   dst_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +   cache_flush=0<o:p></o:p></p>
<p class="MsoPlainText">> +   test_seconds=2<o:p></o:p></p>
<p class="MsoPlainText">> +   <a href="mailto:lcore_dma=lcore10@0000:00:04.2">lcore_dma=lcore10@0000:00:04.2</a>,
<a href="mailto:lcore11@0000:00:04.3">lcore11@0000:00:04.3</a><o:p></o:p></p>
<p class="MsoPlainText">> +   eal_args=--in-memory --file-prefix=test<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +   [case2]<o:p></o:p></p>
<p class="MsoPlainText">> +   type=CPU_MEM_COPY<o:p></o:p></p>
<p class="MsoPlainText">> +   mem_size=10<o:p></o:p></p>
<p class="MsoPlainText">> +   buf_size=64,8192,2,MUL<o:p></o:p></p>
<p class="MsoPlainText">> +   src_numa_node=0<o:p></o:p></p>
<p class="MsoPlainText">> +   dst_numa_node=1<o:p></o:p></p>
<p class="MsoPlainText">> +   cache_flush=0<o:p></o:p></p>
<p class="MsoPlainText">> +   test_seconds=2<o:p></o:p></p>
<p class="MsoPlainText">> +   lcore = 3, 4<o:p></o:p></p>
<p class="MsoPlainText">> +   eal_args=--in-memory --no-pci<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +The configuration file is divided into multiple sections, each
<o:p></o:p></p>
<p class="MsoPlainText">> +section<o:p></o:p></p>
<p class="MsoPlainText">> represents a test case.<o:p></o:p></p>
<p class="MsoPlainText">> +The four variables mem_size, buf_size, dma_ring_size, and kick_batch
<o:p></o:p></p>
<p class="MsoPlainText">> +can<o:p></o:p></p>
<p class="MsoPlainText">> vary in each test case.<o:p></o:p></p>
<p class="MsoPlainText">> +The format for this is ``variable=first,last,increment,ADD\|MUL``.
<o:p></o:p></p>
<p class="MsoPlainText">> +This means that the first value of the variable is 'first', the last
<o:p></o:p></p>
<p class="MsoPlainText">> +value is 'last', 'increment' is the step size, and ADD|MUL indicates
<o:p></o:p></p>
<p class="MsoPlainText">> +whether the change is by addition or multiplication. Each case can
<o:p></o:p></p>
<p class="MsoPlainText">> +only have one<o:p></o:p></p>
<p class="MsoPlainText">> variable change, and each change will generate a scenario, so each
<o:p></o:p></p>
<p class="MsoPlainText">> case can have multiple scenarios.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Parameter Definitions<o:p></o:p></p>
<p class="MsoPlainText">> +---------------------<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +- **type**: The type of the test. Currently supported types are<o:p></o:p></p>
<p class="MsoPlainText">> `DMA_MEM_COPY` and `CPU_MEM_COPY`.<o:p></o:p></p>
<p class="MsoPlainText">> +- **mem_size**: The size of the memory footprint.<o:p></o:p></p>
<p class="MsoPlainText">> +- **buf_size**: The memory size of a single operation.<o:p></o:p></p>
<p class="MsoPlainText">> +- **dma_ring_size**: The DMA ring buffer size. Must be a power of
<o:p></o:p></p>
<p class="MsoPlainText">> +two,<o:p></o:p></p>
<p class="MsoPlainText">> and between 64 and 4096.<o:p></o:p></p>
<p class="MsoPlainText">> +- **kick_batch**: The DMA operation batch size, should be greater
<o:p></o:p></p>
<p class="MsoPlainText">> +than 1<o:p></o:p></p>
<p class="MsoPlainText">> normally.<o:p></o:p></p>
<p class="MsoPlainText">> +- **src_numa_node**: Controls the NUMA node where the source memory<o:p></o:p></p>
<p class="MsoPlainText">> is allocated.<o:p></o:p></p>
<p class="MsoPlainText">> +- **dst_numa_node**: Controls the NUMA node where the destination<o:p></o:p></p>
<p class="MsoPlainText">> memory is allocated.<o:p></o:p></p>
<p class="MsoPlainText">> +- **cache_flush**: Determines whether the cache should be flushed.
<o:p></o:p></p>
<p class="MsoPlainText">> +`1`<o:p></o:p></p>
<p class="MsoPlainText">> indicates to flush and `0` to not flush.<o:p></o:p></p>
<p class="MsoPlainText">> +- **test_seconds**: Controls the test time for each scenario.<o:p></o:p></p>
<p class="MsoPlainText">> +- **lcore_dma**: Specifies the lcore/DMA mapping.<o:p></o:p></p>
<p class="MsoPlainText">> +- **lcore**: Specifies the lcore for CPU testing.<o:p></o:p></p>
<p class="MsoPlainText">> +- **eal_args**: Specifies the EAL arguments.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +.. Note::<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +         The mapping of lcore to DMA must be one-to-one and cannot be<o:p></o:p></p>
<p class="MsoPlainText">> duplicated.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +To specify a configuration file, use the "\-\-config" flag followed
<o:p></o:p></p>
<p class="MsoPlainText">> +by the path<o:p></o:p></p>
<p class="MsoPlainText">> to the file.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +To specify a result file, use the "\-\-result" flag followed by the
<o:p></o:p></p>
<p class="MsoPlainText">> +path to the file. If you do not specify a result file, one will be
<o:p></o:p></p>
<p class="MsoPlainText">> +generated with the same name as the configuration file, with the
<o:p></o:p></p>
<p class="MsoPlainText">> +addition<o:p></o:p></p>
<p class="MsoPlainText">> of "_result.csv" at the end.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Running the Application<o:p></o:p></p>
<p class="MsoPlainText">> +-----------------------<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Typical command-line invocation to execute the application:<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +.. code-block:: console<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +   dpdk-test-dma-perf --config=./config_dma.ini <o:p></o:p></p>
<p class="MsoPlainText">> + --result=./res_dma.csv<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Where `config_dma.ini` is the configuration file, and `res_dma.csv`
<o:p></o:p></p>
<p class="MsoPlainText">> +will be the generated result file.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +After the tests, you can find the results in the `res_dma.csv` file.<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Limitations<o:p></o:p></p>
<p class="MsoPlainText">> +-----------<o:p></o:p></p>
<p class="MsoPlainText">> +<o:p></o:p></p>
<p class="MsoPlainText">> +Currently, this tool only supports memory copy performance tests.<o:p></o:p></p>
<p class="MsoPlainText">> +Additional enhancements are possible in the future to support more
<o:p></o:p></p>
<p class="MsoPlainText">> +types<o:p></o:p></p>
<p class="MsoPlainText">> of tests for DMA devices and CPUs.<o:p></o:p></p>
<p class="MsoPlainText">> diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst
<o:p></o:p></p>
<p class="MsoPlainText">> index<o:p></o:p></p>
<p class="MsoPlainText">> 6f84fc31ff..857572da96 100644<o:p></o:p></p>
<p class="MsoPlainText">> --- a/doc/guides/tools/index.rst<o:p></o:p></p>
<p class="MsoPlainText">> +++ b/doc/guides/tools/index.rst<o:p></o:p></p>
<p class="MsoPlainText">> @@ -23,3 +23,4 @@ DPDK Tools User Guides<o:p></o:p></p>
<p class="MsoPlainText">>      testregex<o:p></o:p></p>
<p class="MsoPlainText">>      testmldev<o:p></o:p></p>
<p class="MsoPlainText">>      dts<o:p></o:p></p>
<p class="MsoPlainText">> +    dmaperf<o:p></o:p></p>
<p class="MsoPlainText">> --<o:p></o:p></p>
<p class="MsoPlainText">> 2.40.1<o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> <o:p></o:p></p>
<p class="MsoPlainText">> End of dev Digest, Vol 462, Issue 27<o:p></o:p></p>
<p class="MsoPlainText">> ************************************<o:p></o:p></p>
</div>
</body>
</html>