<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>