From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0933AA00C5; Thu, 30 Apr 2020 12:35:01 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 805A81DB62; Thu, 30 Apr 2020 12:34:36 +0200 (CEST) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30047.outbound.protection.outlook.com [40.107.3.47]) by dpdk.org (Postfix) with ESMTP id 812701DB37 for ; Thu, 30 Apr 2020 12:34:22 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OQYTpCk9Dtnp/Bfl3ojKe0vAKrOotssOP5KymjkL9O/pOFU8z3rP9rueO4jzh+ucH4W/xhxh8OMkyZrHP7rkiQTcyafjnsjHQclOFflzau1oCiN/BrmOqnNOob3AfKbbkvI3R5v0HDik6AyS1aackBNute6CNqEr74PWFJEswGua1C33Q9onVVItx58toPxIKgxiOlPUQ4DxgSBJNI4cRGW5zcytVWxhI5OJddV2nYQKpaVcVXBgas9Ms8dVn3EVOS1yQ2xuRBY2lnMnE6lI1T9UomsegGLcOJXZW2Xdhq+eF9wYv/gc02nlYIT/qESnJKnZwS9k05QMDe6fVbl68Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=UpJF+vN3khjk/0KvpkCFjGVHnS0O/IgqxoDpACPzP6c=; b=GGez223jY0L2D0HXVLeXGfZXorTNmx8dKpL2YqZGGn/sqlXzZbaPjrEV6uuV0F+I87IrsPgBlZHY6ANufDer6z4GtPaesGAIAcRU6SITWBWL3MzVA8aRDussKGKX4ZFa1gf5qfO2xulQ8ZRBo6wGp/5m50Mnd2VzHAf8bViq3yw5MijSNNoJtrf37+WnGxOmKcOKDvhrUCVNGZ87a63+A+FVNb8zOYkl5NL+O7Bu00sz6Uxu1SBWW8mS6ABZHmQ1c6OU0oU52MH+0Dyzj7Bx7om1bN5MeD8RxOeGxsvYKplJa5q3gcoghkNErB3ep034pITwd8xQR7FDIryBA8bCNQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=mellanox.com; dmarc=pass action=none header.from=mellanox.com; dkim=pass header.d=mellanox.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=UpJF+vN3khjk/0KvpkCFjGVHnS0O/IgqxoDpACPzP6c=; b=KXo3CuNnCMXnN0PaeDfKjhh/sie1SB8iZgLo9lewqh0F5nkbkvLBbib12imrjb4tneaj95nqGTd2WmF5a7rufQK6ZCNBjQz4ODhWPr7AsxaqEZgeLzQ3rMbNh+mnIhRJCPVxmLK2OIsDPezG3D4+Y+N58tJpGpsPhkrnSyva2NU= Authentication-Results: dpdk.org; dkim=none (message not signed) header.d=none;dpdk.org; dmarc=none action=none header.from=mellanox.com; Received: from AM0PR05MB6610.eurprd05.prod.outlook.com (2603:10a6:208:12f::18) by AM0PR05MB5204.eurprd05.prod.outlook.com (2603:10a6:208:ef::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2937.13; Thu, 30 Apr 2020 10:34:21 +0000 Received: from AM0PR05MB6610.eurprd05.prod.outlook.com ([fe80::900:c0ac:78bd:18fc]) by AM0PR05MB6610.eurprd05.prod.outlook.com ([fe80::900:c0ac:78bd:18fc%6]) with mapi id 15.20.2937.028; Thu, 30 Apr 2020 10:34:21 +0000 From: Wisam Jaddo To: dev@dpdk.org, jackmin@mellanox.com, thomas@monjalon.net, jerinjacobk@gmail.com, gerlitz.or@gmail.com, l.yan@epfl.ch Date: Thu, 30 Apr 2020 10:33:41 +0000 Message-Id: <20200430103341.1845-6-wisamm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200430103341.1845-1-wisamm@mellanox.com> References: <20200430093249.6772-2-wisamm@mellanox.com> <20200430103341.1845-1-wisamm@mellanox.com> Content-Type: text/plain X-ClientProxiedBy: PR0P264CA0116.FRAP264.PROD.OUTLOOK.COM (2603:10a6:100:19::32) To AM0PR05MB6610.eurprd05.prod.outlook.com (2603:10a6:208:12f::18) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from mellanox.com (37.142.13.130) by PR0P264CA0116.FRAP264.PROD.OUTLOOK.COM (2603:10a6:100:19::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2958.19 via Frontend Transport; Thu, 30 Apr 2020 10:34:16 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [37.142.13.130] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 88ac37fe-3416-41e3-b4dd-08d7ecf208ed X-MS-TrafficTypeDiagnostic: AM0PR05MB5204:|AM0PR05MB5204: X-LD-Processed: a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:341; X-Forefront-PRVS: 0389EDA07F X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM0PR05MB6610.eurprd05.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(4636009)(396003)(376002)(136003)(346002)(366004)(39860400002)(316002)(8676002)(52116002)(7696005)(478600001)(8936002)(186003)(5660300002)(55016002)(16526019)(6666004)(26005)(36756003)(956004)(8886007)(2616005)(66556008)(2906002)(66476007)(66946007)(86362001)(30864003)(1076003); DIR:OUT; SFP:1101; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PcwICT1b8lUTjDJPgtPFfexZyHnECRB+UN+6R4rvSqVU2X7Hkf+PoNPlY5mnrgiWJJmH4XyzlZa94JjTQWfg1oFm2noPHIB/QhS3K8rZu6goI2bRd0LA7GHgvK0KKpvMsqN+zjKayxXE6M2wlt5+qcfAheNPSLzpapUN8Nz+Uw0yUKDXL7kIVoU4t7tt3BENxeIGvtq2VqHd3IgDZu49YtdyTQMi8pof/xiXiSKQXoVQdkjn8PO3GoZPHwxvbphhWGLif5wibziBrG+6oBycoDDbbOG3GexPg7suy4HT8b12/9gHyy9mcHAANdRuuhkSRDxFN8jB/no/LvcLpb8yjoaQRNp6NL3i/n4KG05QUvBFnfFBU/CmG0E/wI1ICcPe9qRZhT3el0J6kh0B+GqKa5DpxFsOZWEvwjAeXR6DqB7kQtQtn+e664NCVnQ2i2sB X-MS-Exchange-AntiSpam-MessageData: 0DVlpxnRtv0yfilHHefy/jdVslFWiaYqtYsCnxOK2C1FOzG89SLXj53uHgyPv0eUTJel/HmeAPxFhxLoC3dboXePvh6CRplb2TzPxWYeGis443dveVWLXfvOkhRx3uW78IuFHxEzWDVWkgq66EpgVQE1xFb/Kb48zozzNmjLp5K0eg5GZrp8cZCNuJdceULvnff/sh5fsmlKF3SATTyuR1XimYgU0f3ULywQXSEyQSuCgw4biE+FZTxAvqlrBjPZ7jF5OWua/kKwDbLl/2uZEt6o+ZHWWWzMs7wbT2TD2+dV2U8ITyV477bAbV0bRivg9sFw2hGYcB3NcMbkG/m9HYi5FR7SCmHBHD8aB83ohQBRAXfzHenLg0bHFOswdl5tYBC3MlHzW2FWwP2j3XCHpa+2bk4Svu01pLQERfXAPvCig+ZKoVIWlIW76FHMPe2dPPZF20K9vga8Q5apHnQwBYbGQFyoNbOVu5NRNF+CYIggX8wkoqCuRykmU+pFuOmuzmrFRO07RQVsZ+ludopRHHBiLmG1GgluKk5Csc25SM8cmj9cG2cJwuweu2EG1SppBRDUHeOrKM7/DzV+VCzmialCMhP4qbteLV9GAB02kIvwiNG+Na+aZNAS40C4zr5Dq2UgHhgC7dEH9i06YZldjlgsy1M6ZJmt8/elNLfAqNraJpFjxBf4P8VUzHkGgmuofiNu5QFqcEkaE2iSUpoOKmXFO6ePT/mo86W5eUpbwqtyaplCot3NAtK9Q25yU1ZyMoQKgh9MeNKEHzBk0O+vQisZtmZBwsiJHn1Nem23/KY= X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: 88ac37fe-3416-41e3-b4dd-08d7ecf208ed X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Apr 2020 10:34:17.5669 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 5KBF5EcrwpDHmWZAELsRbjgmdMnHbuWlqSAfGZ7psXNywt7KCy/XNrYsDlPJfFiVCK2NxqYvXDRR2158cpHlog== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR05MB5204 Subject: [dpdk-dev] [PATCH v4 5/5] app/test-flow-perf: add packet forwarding support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Introduce packet forwarding support to the app to do some performance measurements. The measurements are reported in term of packet per second unit. The forwarding will start after the end of insertion/deletion operations. The support has single and multi core performance measurements. Signed-off-by: Wisam Jaddo --- app/test-flow-perf/main.c | 300 +++++++++++++++++++++++++++++++++ doc/guides/tools/flow-perf.rst | 6 + 2 files changed, 306 insertions(+) diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c index 95435910de..2596d05dc2 100644 --- a/app/test-flow-perf/main.c +++ b/app/test-flow-perf/main.c @@ -60,14 +60,45 @@ static uint8_t flow_group; static uint16_t flow_items; static uint16_t flow_actions; static uint8_t flow_attrs; + static volatile bool force_quit; static volatile bool dump_iterations; static volatile bool dump_socket_mem_flag; static volatile bool delete_flag; +static volatile bool enable_fwd; + static struct rte_mempool *mbuf_mp; static uint32_t nb_lcores; static uint32_t flows_count; static uint32_t iterations_number; +static uint32_t nb_lcores; + +#define MAX_PKT_BURST 32 +#define LCORE_MODE_PKT 1 +#define LCORE_MODE_STATS 2 +#define MAX_STREAMS 64 +#define MAX_LCORES 64 + +struct stream { + int tx_port; + int tx_queue; + int rx_port; + int rx_queue; +}; + +struct lcore_info { + int mode; + int streams_nb; + struct stream streams[MAX_STREAMS]; + /* stats */ + uint64_t tx_pkts; + uint64_t tx_drops; + uint64_t rx_pkts; + struct rte_mbuf *pkts[MAX_PKT_BURST]; +} __attribute__((__aligned__(64))); /* let it be cacheline aligned */ + + +static struct lcore_info lcore_infos[MAX_LCORES]; static void usage(char *progname) { @@ -80,6 +111,8 @@ static void usage(char *progname) printf(" --deletion-rate: Enable deletion rate" " calculations\n"); printf(" --dump-socket-mem: to dump all socket memory\n"); + printf(" --enable-fwd: to enable packets forwarding" + " after insertion\n"); printf("To set flow attributes:\n"); printf(" --ingress: set ingress attribute in flows\n"); @@ -130,6 +163,7 @@ args_parse(int argc, char **argv) { "dump-iterations", 0, 0, 0 }, { "deletion-rate", 0, 0, 0 }, { "dump-socket-mem", 0, 0, 0 }, + { "enable-fwd", 0, 0, 0 }, /* Attributes */ { "ingress", 0, 0, 0 }, { "egress", 0, 0, 0 }, @@ -315,6 +349,8 @@ args_parse(int argc, char **argv) delete_flag = true; if (!strcmp(lgopts[opt_idx].name, "dump-socket-mem")) dump_socket_mem_flag = true; + if (!strcmp(lgopts[opt_idx].name, "enable-fwd")) + enable_fwd = true; break; default: usage(argv[0]); @@ -582,6 +618,265 @@ signal_handler(int signum) } } +static inline uint16_t +do_rx(struct lcore_info *li, uint16_t rx_port, uint16_t rx_queue) +{ + uint16_t cnt = 0; + cnt = rte_eth_rx_burst(rx_port, rx_queue, li->pkts, MAX_PKT_BURST); + li->rx_pkts += cnt; + return cnt; +} + +static inline void +do_tx(struct lcore_info *li, uint16_t cnt, uint16_t tx_port, + uint16_t tx_queue) +{ + uint16_t nr_tx = 0; + uint16_t i; + + nr_tx = rte_eth_tx_burst(tx_port, tx_queue, li->pkts, cnt); + li->tx_pkts += nr_tx; + li->tx_drops += cnt - nr_tx; + + for (i = nr_tx; i < cnt; i++) + rte_pktmbuf_free(li->pkts[i]); +} + +/* + * Method to convert numbers into pretty numbers that easy + * to read. The design here is to add comma after each three + * digits and set all of this inside buffer. + * + * For example if n = 1799321, the output will be + * 1,799,321 after this method which is easier to read. + */ +static char * +pretty_number(uint64_t n, char *buf) +{ + char p[6][4]; + int i = 0; + int off = 0; + + while (n > 1000) { + sprintf(p[i], "%03d", (int)(n % 1000)); + n /= 1000; + i += 1; + } + + sprintf(p[i++], "%d", (int)n); + + while (i--) + off += sprintf(buf + off, "%s,", p[i]); + buf[strlen(buf) - 1] = '\0'; + + return buf; +} + +static void +packet_per_second_stats(void) +{ + struct lcore_info *old; + struct lcore_info *li, *oli; + int nr_lines = 0; + int i; + + old = rte_zmalloc("old", + sizeof(struct lcore_info) * MAX_LCORES, 0); + if (old == NULL) + rte_exit(EXIT_FAILURE, "No Memory available!"); + + memcpy(old, lcore_infos, + sizeof(struct lcore_info) * MAX_LCORES); + + while (!force_quit) { + uint64_t total_tx_pkts = 0; + uint64_t total_rx_pkts = 0; + uint64_t total_tx_drops = 0; + uint64_t tx_delta, rx_delta, drops_delta; + char buf[3][32]; + int nr_valid_core = 0; + + sleep(1); + + if (nr_lines) { + char go_up_nr_lines[16]; + + sprintf(go_up_nr_lines, "%c[%dA\r", 27, nr_lines); + printf("%s\r", go_up_nr_lines); + } + + printf("\n%6s %16s %16s %16s\n", "core", "tx", "tx drops", "rx"); + printf("%6s %16s %16s %16s\n", "------", "----------------", + "----------------", "----------------"); + nr_lines = 3; + for (i = 0; i < MAX_LCORES; i++) { + li = &lcore_infos[i]; + oli = &old[i]; + if (li->mode != LCORE_MODE_PKT) + continue; + + tx_delta = li->tx_pkts - oli->tx_pkts; + rx_delta = li->rx_pkts - oli->rx_pkts; + drops_delta = li->tx_drops - oli->tx_drops; + printf("%6d %16s %16s %16s\n", i, + pretty_number(tx_delta, buf[0]), + pretty_number(drops_delta, buf[1]), + pretty_number(rx_delta, buf[2])); + + total_tx_pkts += tx_delta; + total_rx_pkts += rx_delta; + total_tx_drops += drops_delta; + + nr_valid_core++; + nr_lines += 1; + } + + if (nr_valid_core > 1) { + printf("%6s %16s %16s %16s\n", "total", + pretty_number(total_tx_pkts, buf[0]), + pretty_number(total_tx_drops, buf[1]), + pretty_number(total_rx_pkts, buf[2])); + nr_lines += 1; + } + + memcpy(old, lcore_infos, + sizeof(struct lcore_info) * MAX_LCORES); + } +} + +static int +start_forwarding(void *data __rte_unused) +{ + int lcore = rte_lcore_id(); + int stream_id; + uint16_t cnt; + struct lcore_info *li = &lcore_infos[lcore]; + + if (!li->mode) + return 0; + + if (li->mode == LCORE_MODE_STATS) { + printf(":: started stats on lcore %u\n", lcore); + packet_per_second_stats(); + return 0; + } + + while (!force_quit) + for (stream_id = 0; stream_id < MAX_STREAMS; stream_id++) { + if (li->streams[stream_id].rx_port == -1) + continue; + + cnt = do_rx(li, + li->streams[stream_id].rx_port, + li->streams[stream_id].rx_queue); + if (cnt) + do_tx(li, cnt, + li->streams[stream_id].tx_port, + li->streams[stream_id].tx_queue); + } + return 0; +} + +static void +init_lcore_info(void) +{ + int i, j; + unsigned int lcore; + uint16_t nr_port; + uint16_t queue; + int port; + int stream_id = 0; + int streams_per_core; + int unassigned_streams; + int nb_fwd_streams; + nr_port = rte_eth_dev_count_avail(); + + /* First logical core is reserved for stats printing */ + lcore = rte_get_next_lcore(-1, 0, 0); + lcore_infos[lcore].mode = LCORE_MODE_STATS; + + /* + * Initialize all cores + * All cores at first must have -1 value in all streams + * This means that this stream is not used, or not set + * yet. + */ + for (i = 0; i < MAX_LCORES; i++) + for (j = 0; j < MAX_STREAMS; j++) { + lcore_infos[i].streams[j].tx_port = -1; + lcore_infos[i].streams[j].rx_port = -1; + lcore_infos[i].streams[j].tx_queue = -1; + lcore_infos[i].streams[j].rx_queue = -1; + lcore_infos[i].streams_nb = 0; + } + + /* + * Calculate the total streams count. + * Also distribute those streams count between the available + * logical cores except first core, since it's reserved for + * stats prints. + */ + nb_fwd_streams = nr_port * RXQs; + if ((int)(nb_lcores - 1) >= nb_fwd_streams) + for (i = 0; i < (int)(nb_lcores - 1); i++) { + lcore = rte_get_next_lcore(lcore, 0, 0); + lcore_infos[lcore].streams_nb = 1; + } + else { + streams_per_core = nb_fwd_streams / (nb_lcores - 1); + unassigned_streams = nb_fwd_streams % (nb_lcores - 1); + for (i = 0; i < (int)(nb_lcores - 1); i++) { + lcore = rte_get_next_lcore(lcore, 0, 0); + lcore_infos[lcore].streams_nb = streams_per_core; + if (unassigned_streams) { + lcore_infos[lcore].streams_nb++; + unassigned_streams--; + } + } + } + + /* + * Set the streams for the cores according to each logical + * core stream count. + * The streams is built on the design of what received should + * forward as well, this means that if you received packets on + * port 0 queue 0 then the same queue should forward the + * packets, using the same logical core. + */ + lcore = rte_get_next_lcore(-1, 0, 0); + for (port = 0; port < nr_port; port++) { + /** Create FWD stream **/ + for (queue = 0; queue < RXQs; queue++) { + if (!lcore_infos[lcore].streams_nb || + !(stream_id % lcore_infos[lcore].streams_nb)) { + lcore = rte_get_next_lcore(lcore, 0, 0); + lcore_infos[lcore].mode = LCORE_MODE_PKT; + stream_id = 0; + } + lcore_infos[lcore].streams[stream_id].rx_queue = queue; + lcore_infos[lcore].streams[stream_id].tx_queue = queue; + lcore_infos[lcore].streams[stream_id].rx_port = port; + lcore_infos[lcore].streams[stream_id].tx_port = port; + stream_id++; + } + } + + /** Print all streams **/ + printf(":: Stream -> core id[N]: (rx_port, rx_queue)->(tx_port, tx_queue)\n"); + for (i = 0; i < MAX_LCORES; i++) + for (j = 0; j < MAX_STREAMS; j++) { + /** No streams for this core **/ + if (lcore_infos[i].streams[j].tx_port == -1) + break; + printf("Stream -> core id[%d]: (%d,%d)->(%d,%d)\n", + i, + lcore_infos[i].streams[j].rx_port, + lcore_infos[i].streams[j].rx_queue, + lcore_infos[i].streams[j].tx_port, + lcore_infos[i].streams[j].tx_queue); + } +} + static void init_port(void) { @@ -757,6 +1052,11 @@ main(int argc, char **argv) fprintf(stdout, ":: Memory allocation change(M): %.6lf\n", (alloc - last_alloc) / 1.0e6); + if (enable_fwd) { + init_lcore_info(); + rte_eal_mp_remote_launch(start_forwarding, NULL, CALL_MASTER); + } + RTE_LCORE_FOREACH_SLAVE(lcore_id) if (rte_eal_wait_lcore(lcore_id) < 0) diff --git a/doc/guides/tools/flow-perf.rst b/doc/guides/tools/flow-perf.rst index 28d452fd06..ecd760de81 100644 --- a/doc/guides/tools/flow-perf.rst +++ b/doc/guides/tools/flow-perf.rst @@ -21,6 +21,8 @@ have a multi core insertion rate measurement support in the app. The application also provide the ability to measure rte flow deletion rate, in addition to memory consumption before and after the flows creation. +The app supports single and multi core performance measurements. + Compiling the Application ========================= @@ -98,6 +100,10 @@ The command line options are: * ``--dump-socket-mem`` Dump the memory stats for each socket before the insertion and after. +* ``enable-fwd`` + Enable packets forwarding after insertion/deletion operations. + + Attributes: * ``--ingress`` -- 2.17.1