From patchwork Fri Jan 21 10:31:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106162 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 56A06A034E; Fri, 21 Jan 2022 11:31:38 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E326A4274B; Fri, 21 Jan 2022 11:31:33 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id CD49540042 for ; Fri, 21 Jan 2022 11:31:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761092; x=1674297092; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=91BuGmLS8tjq2kdFkJkABz4t618UqoaKsJyobTy/HtE=; b=XfaKcIPwGXPQbGwmYlzkSFhXE1/z3cuvl/NdLrhz6BtzN0ldts+LAdDF fgcrokvpqS1HO7QSOnf5Tzq5tYZ4zPe56Sd5kXUbQfokwaa0EZXKZyaKR hg1WCKD1KiTxOjfK1L7T4kklCmxZeB2xSiQA5g+Wk2JxLTkZat2no5XDF 99PbFdyruGxz88a0VczqhJCgU5Z0xh65DvlaVDh8SdQ3aMGRzMssRE4ej D/3AlrRKmCPOsDBJwk2nfY+lCQgbmINRM+X3e2vPyQQZkI8DKyt4GkOGe 80MT8PoEpi3/SUSnUhn4dkBoy0L0Y88avdbb/LmP1jADVK5lKEnfrsYrm Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045062" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045062" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222699" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:30 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles , Harry van Haaren Subject: [PATCH v2 01/15] net: add string to IPv4 parse function Date: Fri, 21 Jan 2022 10:31:08 +0000 Message-Id: <20220121103122.2926856-2-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Added function that accepts ip string as a parameter and returns an ip address represented by a uint32_t. Relevant unit test for this function is also included. Signed-off-by: Harry van Haaren Signed-off-by: Ronan Randles --- app/test/meson.build | 2 ++ app/test/test_net.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ lib/net/meson.build | 1 + lib/net/rte_ip.c | 43 +++++++++++++++++++++++++++++++ lib/net/rte_ip.h | 18 +++++++++++++ lib/net/version.map | 6 +++++ 6 files changed, 131 insertions(+) create mode 100644 app/test/test_net.c create mode 100644 lib/net/rte_ip.c diff --git a/app/test/meson.build b/app/test/meson.build index 344a609a4d..8cdfb783a9 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -100,6 +100,7 @@ test_sources = files( 'test_meter.c', 'test_mcslock.c', 'test_mp_secondary.c', + 'test_net.c', 'test_per_lcore.c', 'test_pflock.c', 'test_pmd_perf.c', @@ -177,6 +178,7 @@ test_deps = [ 'ipsec', 'lpm', 'member', + 'net', 'node', 'pipeline', 'port', diff --git a/app/test/test_net.c b/app/test/test_net.c new file mode 100644 index 0000000000..2cb7d3e1c9 --- /dev/null +++ b/app/test/test_net.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Intel Corporation + */ + +#include +#include + +#include +#include +#include "test.h" + +static int +test_rte_ip_parse_addr(void) +{ + printf("Running IP parsing tests...\n"); + + struct str_ip_t { + const char *str; + uint32_t exp_output; + uint32_t expected_to_fail; + } str_ip_tests[] = { + { .str = "1.2.3.4", .exp_output = RTE_IPV4(1, 2, 3, 4)}, + { .str = "192.168.255.255", .exp_output = + RTE_IPV4(192, 168, 255, 255)}, + { .str = "172.16.0.9", .exp_output = + RTE_IPV4(172, 16, 0, 9)}, + { .str = "1.2.3", .expected_to_fail = 1}, + { .str = "1.2.3.4.5", .expected_to_fail = 1}, + { .str = "fail.1.2.3", .expected_to_fail = 1}, + { .str = "", .expected_to_fail = 1}, + { .str = "1.2.3.fail", .expected_to_fail = 1} + }; + + uint32_t i; + for (i = 0; i < RTE_DIM(str_ip_tests); i++) { + uint32_t test_addr; + int32_t err = rte_ip_parse_addr(str_ip_tests[i].str, + &test_addr); + if (!test_addr) { + if (str_ip_tests[i].expected_to_fail != 1) + return -1; + } + + if (err || test_addr != str_ip_tests[i].exp_output) { + if (str_ip_tests[i].expected_to_fail != 1) + return -1; + } + } + + + return 0; +} + +static int +test_net_tests(void) +{ + int ret = test_rte_ip_parse_addr(); + return ret; +} + +REGISTER_TEST_COMMAND(net_autotest, test_net_tests); diff --git a/lib/net/meson.build b/lib/net/meson.build index e899846578..b2577a7592 100644 --- a/lib/net/meson.build +++ b/lib/net/meson.build @@ -26,6 +26,7 @@ headers = files( sources = files( 'rte_arp.c', 'rte_ether.c', + 'rte_ip.c', 'rte_net.c', 'rte_net_crc.c', ) diff --git a/lib/net/rte_ip.c b/lib/net/rte_ip.c new file mode 100644 index 0000000000..b859dfb640 --- /dev/null +++ b/lib/net/rte_ip.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Intel Corporation + */ + +#include +#include + +int32_t +rte_ip_parse_addr(const char *src_ip, uint32_t *output_addr) +{ + int32_t ret = 0; + char *current_position; + + if (src_ip == NULL) + return -1; + + char *tok = strdup(src_ip); + if (tok == NULL) + return -1; + + char *current_digit = strtok_r(tok, ".", ¤t_position); + + *output_addr = 0; + uint32_t i = 0; + while (current_digit) { + uint32_t shift = ((3 - i) * 8); + unsigned long parsed_value = strtoul(current_digit, NULL, 0) + << shift; + + if (parsed_value == 0 && strcmp(current_digit, "0")) + break; + + *output_addr |= parsed_value; + current_digit = strtok_r(NULL, ".", ¤t_position); + i++; + + } + if (i != 4) + return -1; + + free(tok); + return ret; +} diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index c575250852..188054fda4 100644 --- a/lib/net/rte_ip.h +++ b/lib/net/rte_ip.h @@ -426,6 +426,24 @@ rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, return 0; } +/** + * IP address parser. + * + * @param src_ip + * The IP address to be parsed. + * @param output_addr + * The array in which the parsed digits will be saved. + * + * @retval 0 + * Success. + * @retval -1 + * Failure due to invalid input arguments. + */ + +__rte_experimental +int32_t +rte_ip_parse_addr(const char *src_ip, uint32_t *output_addr); + /** * IPv6 Header */ diff --git a/lib/net/version.map b/lib/net/version.map index 4f4330d1c4..c530d1a4e4 100644 --- a/lib/net/version.map +++ b/lib/net/version.map @@ -12,3 +12,9 @@ DPDK_22 { local: *; }; + +EXPERIMENTAL { + global: + + rte_ip_parse_addr; +}; From patchwork Fri Jan 21 10:31:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106163 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 006AEA034E; Fri, 21 Jan 2022 11:31:44 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B299842751; Fri, 21 Jan 2022 11:31:34 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id C5B1940042 for ; Fri, 21 Jan 2022 11:31:32 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761093; x=1674297093; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5+UYx+hbjVJM/7fvf5oUftHOMI30Hf333p11TZUG+qc=; b=NZXQl9GwZUHmrcftss8MFlL+7PkofJjBugv0peroS61toDC+ipoU0fXQ Y48dYl8adt/VjlZXkJ6z9a4Xy4EYeszUN4ArE/vx6nqN2wbXbHH3fnh9v DliJVag70ZDGYLiAVlUvyWBJBwn81Ay+uEY1bs/MUFXj8MUWY9FjZZaOS rDTf0IaEXb95q6yquWeAYtMvbOQVI0K7AjnSCuuW0YgpyfVK8BCR8vOjT FBAOUdgafiqZMnxm61i+XzC728dvHNqcJ1HLOibgQK7gzMe8JY8VUsU0y NCX9RwAO91CwZLyjBIXdzmwjVRxBKGPCO5BKwFOAFB9w603C53lCFcsbC A==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045070" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045070" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:32 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222716" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:31 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 02/15] net: add function to pretty print IPv4 Date: Fri, 21 Jan 2022 10:31:09 +0000 Message-Id: <20220121103122.2926856-3-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This function accepts an uint32_t representation of an IP address and produces a string representation stored in a char * buffer. Realavent unit tests also included. Signed-off-by: Ronan Randles --- app/test/test_net.c | 26 ++++++++++++++++++++++++++ lib/net/rte_ip.c | 15 +++++++++++++++ lib/net/rte_ip.h | 20 ++++++++++++++++++++ lib/net/version.map | 1 + 4 files changed, 62 insertions(+) diff --git a/app/test/test_net.c b/app/test/test_net.c index 2cb7d3e1c9..75beeea671 100644 --- a/app/test/test_net.c +++ b/app/test/test_net.c @@ -46,7 +46,32 @@ test_rte_ip_parse_addr(void) return -1; } } + return 0; +} + +static int +test_rte_ip_print_addr(void) +{ + printf("Running IP printing tests...\n"); + char buffer[128]; + struct ip_str_t { + uint32_t ip_addr; + const char *exp_output; + } ip_str_tests[] = { + { .ip_addr = 16909060, .exp_output = "1.2.3.4"}, + { .ip_addr = 3232301055, . exp_output = "192.168.255.255"}, + { .ip_addr = 2886729737, .exp_output = "172.16.0.9"} + }; + + uint32_t i; + for (i = 0; i < RTE_DIM(ip_str_tests); i++) { + int32_t err = rte_ip_print_addr(ip_str_tests[i].ip_addr, + buffer, 128); + + if (err || strcmp(buffer, ip_str_tests[i].exp_output)) + return -1; + } return 0; } @@ -55,6 +80,7 @@ static int test_net_tests(void) { int ret = test_rte_ip_parse_addr(); + ret += test_rte_ip_print_addr(); return ret; } diff --git a/lib/net/rte_ip.c b/lib/net/rte_ip.c index b859dfb640..fbd9161317 100644 --- a/lib/net/rte_ip.c +++ b/lib/net/rte_ip.c @@ -41,3 +41,18 @@ rte_ip_parse_addr(const char *src_ip, uint32_t *output_addr) free(tok); return ret; } + +int32_t +rte_ip_print_addr(uint32_t ip_addr, char *buffer, uint32_t buffer_size) +{ + if (buffer == NULL) + return -1; + + snprintf(buffer, buffer_size, "%u.%u.%u.%u", + (ip_addr >> 24), + (ip_addr >> 16) & UINT8_MAX, + (ip_addr >> 8) & UINT8_MAX, + ip_addr & UINT8_MAX); + + return 0; +} diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index 188054fda4..e46f0b41ba 100644 --- a/lib/net/rte_ip.h +++ b/lib/net/rte_ip.h @@ -444,6 +444,26 @@ __rte_experimental int32_t rte_ip_parse_addr(const char *src_ip, uint32_t *output_addr); + +/** + * Print IP address from 32 bit int into char * buffer. + * + * @param ip_addr + * ip address to be printed. + * @param buffer + * The buffer the string will be saved into. + * @param buffer_size + * size of buffer to be used. + * + * @retval 0 + * Success. + * @retval -1 + * Failure due to invalid input arguments. + */ +__rte_experimental +int32_t +rte_ip_print_addr(uint32_t ip_addr, char *buffer, uint32_t buffer_size); + /** * IPv6 Header */ diff --git a/lib/net/version.map b/lib/net/version.map index c530d1a4e4..7fe9892d03 100644 --- a/lib/net/version.map +++ b/lib/net/version.map @@ -17,4 +17,5 @@ EXPERIMENTAL { global: rte_ip_parse_addr; + rte_ip_print_addr; }; From patchwork Fri Jan 21 10:31:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106164 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 5DE59A034E; Fri, 21 Jan 2022 11:31:49 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9BA514274A; Fri, 21 Jan 2022 11:31:36 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id D2E3842754 for ; Fri, 21 Jan 2022 11:31:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761095; x=1674297095; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lNV9QpL3SR578dqpveeWbqTPOd45ffJo2QerlJZ5vuk=; b=O1EBs5OY8mgkZgw2GIjiQk0SzNcGsEKrC+khufPB/gu4sfGed90wxyon ZcSVeOxUbayhUYuHTbtSPXgLQUN7t00fH6G8DI0kU0KE3XF6H9m6BEfAn gKPVZMlE2jva4bPj5FVn62pV+wnnHotWAXS/uFcUhoeAxhs/j6RsHGoKZ 8kWS193eeHt/UQVaG7X33hpsP1Dn6zS4JMAS5XJN2hy7IRAgILLChsKMq iCTnzOzMI8/Or6veN/hX2KkKYh9V2tamW6nJgYwECrUWVfkLW8bnBbXlD yZaGTV+PH20Du72wHpsKb4eGzPFixYVoiZAQlfoxsfQA8Is7Rc2Z+wniq g==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045081" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045081" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222731" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:32 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren , Ronan Randles Subject: [PATCH v2 03/15] gen: add files for initial traffic generation library Date: Fri, 21 Jan 2022 10:31:10 +0000 Message-Id: <20220121103122.2926856-4-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren This commit adds empty files to the DPDK build for a traffic generation library, including the bare create and destroy functions. Unit testing infrastructure is added for the create function. Signed-off-by: Harry van Haaren Signed-off-by: Ronan Randles --- app/test/meson.build | 2 ++ app/test/test_gen.c | 55 +++++++++++++++++++++++++++++++++++++++ doc/api/doxy-api-index.md | 3 ++- doc/api/doxy-api.conf.in | 1 + lib/gen/meson.build | 5 ++++ lib/gen/rte_gen.c | 33 +++++++++++++++++++++++ lib/gen/rte_gen.h | 44 +++++++++++++++++++++++++++++++ lib/gen/version.map | 6 +++++ lib/meson.build | 1 + 9 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 app/test/test_gen.c create mode 100644 lib/gen/meson.build create mode 100644 lib/gen/rte_gen.c create mode 100644 lib/gen/rte_gen.h create mode 100644 lib/gen/version.map diff --git a/app/test/meson.build b/app/test/meson.build index 8cdfb783a9..c282493d10 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -66,6 +66,7 @@ test_sources = files( 'test_fib6_perf.c', 'test_func_reentrancy.c', 'test_flow_classify.c', + 'test_gen.c', 'test_graph.c', 'test_graph_perf.c', 'test_hash.c', @@ -173,6 +174,7 @@ test_deps = [ 'eventdev', 'fib', 'flow_classify', + 'gen', 'graph', 'hash', 'ipsec', diff --git a/app/test/test_gen.c b/app/test/test_gen.c new file mode 100644 index 0000000000..f53f4a6608 --- /dev/null +++ b/app/test/test_gen.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Intel Corporation + */ + +#include +#include +#include + +#include "test.h" + +static struct rte_mempool *mp; + +static int +testsuite_setup(void) +{ + if (!mp) { + mp = rte_pktmbuf_pool_create("test_gen_mp", 8192, 256, 0, 2048, + SOCKET_ID_ANY); + } + return mp ? TEST_SUCCESS : TEST_FAILED; +} + +static void +testsuite_teardown(void) +{ + rte_mempool_free(mp); +} + +static int +test_gen_create(void) +{ + struct rte_gen *gen = rte_gen_create(mp); + TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); + + rte_gen_destroy(gen); + return 0; +} + +static struct unit_test_suite gen_suite = { + .suite_name = "gen: packet generator unit test suite", + .setup = testsuite_setup, + .teardown = testsuite_teardown, + .unit_test_cases = { + TEST_CASE_ST(NULL, NULL, test_gen_create), + TEST_CASES_END() /**< NULL terminate unit test array */ + } +}; + +static int +test_gen_suite(void) +{ + return unit_test_suite_runner(&gen_suite); +} + +REGISTER_TEST_COMMAND(gen_autotest, test_gen_suite); diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 4245b9635c..f7ddadd21a 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -220,7 +220,8 @@ The public API headers are grouped by topics: [log] (@ref rte_log.h), [errno] (@ref rte_errno.h), [trace] (@ref rte_trace.h), - [trace_point] (@ref rte_trace_point.h) + [trace_point] (@ref rte_trace_point.h), + [gen] (@ref rte_gen.h) - **misc**: [EAL config] (@ref rte_eal.h), diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in index db2ca9b6ed..6344e949d9 100644 --- a/doc/api/doxy-api.conf.in +++ b/doc/api/doxy-api.conf.in @@ -41,6 +41,7 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \ @TOPDIR@/lib/eventdev \ @TOPDIR@/lib/fib \ @TOPDIR@/lib/flow_classify \ + @TOPDIR@/lib/gen \ @TOPDIR@/lib/gpudev \ @TOPDIR@/lib/graph \ @TOPDIR@/lib/gro \ diff --git a/lib/gen/meson.build b/lib/gen/meson.build new file mode 100644 index 0000000000..3c5d854645 --- /dev/null +++ b/lib/gen/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2021 Intel Corporation + +sources = files('rte_gen.c') +headers = files('rte_gen.h') diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c new file mode 100644 index 0000000000..d993772422 --- /dev/null +++ b/lib/gen/rte_gen.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Intel Corporation + */ + +#include "rte_gen.h" + +#include + +/** Structure that represents a traffic generator. */ +struct rte_gen { + /* Mempool that buffers are retrieved from. */ + struct rte_mempool *mp; +}; + +/* Allocate and initialize a traffic generator instance. */ +struct rte_gen * +rte_gen_create(struct rte_mempool *mempool) +{ + struct rte_gen *gen = rte_zmalloc(NULL, sizeof(*gen), 0); + if (gen == NULL) + return NULL; + + gen->mp = mempool; + + return gen; +} + +/* Free a traffic generator instance. */ +void +rte_gen_destroy(struct rte_gen *gen) +{ + rte_free(gen); +} diff --git a/lib/gen/rte_gen.h b/lib/gen/rte_gen.h new file mode 100644 index 0000000000..5b30430f9e --- /dev/null +++ b/lib/gen/rte_gen.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Intel Corporation + */ + +#ifndef _RTE_GEN_H_ +#define _RTE_GEN_H_ + +/** + * @file + * RTE gen + * + * A library for the generation of packets, to allow easy generation + * of various flows of packets. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Structure that represents a logical traffic generator. */ +struct rte_gen; + +/* Forward declarations for DPDK componeents. */ +struct rte_mempool; + +/* Allocate and initialize a traffic generator instance. */ +__rte_experimental +struct rte_gen * +rte_gen_create(struct rte_mempool *mempool); + +/* Free a traffic generator instance. */ +__rte_experimental +void +rte_gen_destroy(struct rte_gen *gen); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_GEN_H_ */ diff --git a/lib/gen/version.map b/lib/gen/version.map new file mode 100644 index 0000000000..d8a26eb53a --- /dev/null +++ b/lib/gen/version.map @@ -0,0 +1,6 @@ +EXPERIMENTAL { + global: + + rte_gen_create; + rte_gen_destroy; +}; diff --git a/lib/meson.build b/lib/meson.build index fbaa6ef7c2..bdddc059ca 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -35,6 +35,7 @@ libraries = [ 'efd', 'eventdev', 'gpudev', + 'gen', 'gro', 'gso', 'ip_frag', From patchwork Fri Jan 21 10:31:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106165 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 573D7A034E; Fri, 21 Jan 2022 11:31:55 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8C29D42759; Fri, 21 Jan 2022 11:31:37 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id AA68742754 for ; Fri, 21 Jan 2022 11:31:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761095; x=1674297095; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WAsB5mXVwWeKQGOlTBvfEyGz03MD12da3+NZ+S40ePA=; b=dH5be0HRqcqMHl2oZXdmelT6hk55XW+kCueDftxLQxSZmXkGMwFkiMnX 68xdqgmpSxsiuC1qp67FZ2ixPt/NWcUVK4O8RYHEeS+qbidq7RXAognaY JsAXU6cV02t1jPXKpVXxMQX1OqIZsLBHhcUlphVSbiEv+fVb5PBI0MN+U sC94doex9MQ1G2P3pokH2fszN0AcggvvOGoqmpGDmb9i4JpbMRQ1/ATN4 VgR0DIbN8G02OyTNzNOvLWk28Q2Ih/u1HDtoNh4SsMFqd0+/n/itYs1li jf5BVxcBwD0J86/43/BbZNZZwLi5Ii12zLemNd9zeB/4T2OH4f1+MRGvC A==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045085" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045085" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222739" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:33 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren , Ronan Randles Subject: [PATCH v2 04/15] gen: add basic Rx and Tx routines and tests Date: Fri, 21 Jan 2022 10:31:11 +0000 Message-Id: <20220121103122.2926856-5-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren This commit introduces functions for basic mbuf rx and tx. This commit also contains a unit test that calls rte_gen_rx_burst and rte_gen_tx_burst to send bursts of 32 packets repeatedly in order to verify their functionality Signed-off-by: Harry van Haaren Signed-off-by: Ronan Randles --- app/test/test_gen.c | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/gen/meson.build | 1 + lib/gen/rte_gen.c | 43 +++++++++++++++++++++++++++++++++++++++ lib/gen/rte_gen.h | 49 +++++++++++++++++++++++++++++++++++++++++++++ lib/gen/version.map | 2 ++ 5 files changed, 141 insertions(+) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index f53f4a6608..ceacd8c7c4 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -8,6 +8,8 @@ #include "test.h" +#define BURST_MAX 32 + static struct rte_mempool *mp; static int @@ -36,12 +38,56 @@ test_gen_create(void) return 0; } +static int +test_gen_basic_rxtx(void) +{ + struct rte_gen *gen = rte_gen_create(mp); + TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); + + struct rte_mbuf *bufs[BURST_MAX]; + uint16_t nb_rx = rte_gen_rx_burst(gen, bufs, BURST_MAX); + TEST_ASSERT_EQUAL(nb_rx, BURST_MAX, "Expected rx packet burst."); + + uint64_t latency[BURST_MAX]; + uint16_t nb_tx = rte_gen_tx_burst(gen, bufs, latency, BURST_MAX); + TEST_ASSERT_EQUAL(nb_tx, BURST_MAX, "Expected tx packet burst."); + + rte_gen_destroy(gen); + return 0; +} + +static int +test_gen_loop_rxtx(void) +{ + struct rte_gen *gen = rte_gen_create(mp); + TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); + + uint32_t total_sent = 0; + + while (total_sent < 1000000) { + struct rte_mbuf *bufs[BURST_MAX]; + uint16_t nb_rx = rte_gen_rx_burst(gen, bufs, BURST_MAX); + TEST_ASSERT_EQUAL(nb_rx, BURST_MAX, "Expected rx packet burst."); + + uint64_t latency[BURST_MAX]; + uint16_t nb_tx = rte_gen_tx_burst(gen, bufs, latency, nb_rx); + TEST_ASSERT_EQUAL(nb_tx, BURST_MAX, "Expected tx packet burst."); + + total_sent += nb_tx; + } + + rte_gen_destroy(gen); + return 0; +} + static struct unit_test_suite gen_suite = { .suite_name = "gen: packet generator unit test suite", .setup = testsuite_setup, .teardown = testsuite_teardown, .unit_test_cases = { TEST_CASE_ST(NULL, NULL, test_gen_create), + TEST_CASE_ST(NULL, NULL, test_gen_basic_rxtx), + TEST_CASE_ST(NULL, NULL, test_gen_loop_rxtx), TEST_CASES_END() /**< NULL terminate unit test array */ } }; diff --git a/lib/gen/meson.build b/lib/gen/meson.build index 3c5d854645..753984cbba 100644 --- a/lib/gen/meson.build +++ b/lib/gen/meson.build @@ -3,3 +3,4 @@ sources = files('rte_gen.c') headers = files('rte_gen.h') +deps += ['mempool', 'mbuf'] diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index d993772422..f0ad57fa81 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -4,8 +4,11 @@ #include "rte_gen.h" +#include #include +#define GEN_MAX_BURST 32 + /** Structure that represents a traffic generator. */ struct rte_gen { /* Mempool that buffers are retrieved from. */ @@ -31,3 +34,43 @@ rte_gen_destroy(struct rte_gen *gen) { rte_free(gen); } + +uint16_t +rte_gen_rx_burst(struct rte_gen *gen, + struct rte_mbuf **rx_pkts, + const uint16_t nb_pkts) +{ + /* Get a bulk of nb_pkts from the mempool. */ + int err = rte_mempool_get_bulk(gen->mp, (void **)rx_pkts, nb_pkts); + if (err) + return 0; + + const uint32_t pkt_len = 64; + + uint32_t i; + for (i = 0; i < nb_pkts; i++) { + struct rte_mbuf *m = rx_pkts[i]; + uint8_t *pkt_data = rte_pktmbuf_mtod(m, uint8_t *); + + memset(pkt_data, 0, pkt_len); + + m->pkt_len = pkt_len; + m->data_len = pkt_len; + } + + return nb_pkts; +} + +uint16_t +rte_gen_tx_burst(struct rte_gen *gen, + struct rte_mbuf **tx_pkts, + uint64_t *pkt_latencies, + const uint16_t nb_pkts) +{ + RTE_SET_USED(gen); + RTE_SET_USED(pkt_latencies); + + rte_pktmbuf_free_bulk(tx_pkts, nb_pkts); + + return nb_pkts; +} diff --git a/lib/gen/rte_gen.h b/lib/gen/rte_gen.h index 5b30430f9e..09ee1e8872 100644 --- a/lib/gen/rte_gen.h +++ b/lib/gen/rte_gen.h @@ -25,6 +25,7 @@ extern "C" { struct rte_gen; /* Forward declarations for DPDK componeents. */ +struct rte_mbuf; struct rte_mempool; /* Allocate and initialize a traffic generator instance. */ @@ -37,6 +38,54 @@ __rte_experimental void rte_gen_destroy(struct rte_gen *gen); +/** + * Call to receive a burst of generated packets + * + * @param gen + * Gen instance to be used. + * @param rx_pkts + * mbuf where packets will be generated. + * @param nb_pkts + * number of packets to be generated + * + * @retval nb_pkts + * On success the number of rx'ed packets will be returned + * @retval 0 + * Failure. + */ +__rte_experimental +uint16_t +rte_gen_rx_burst(struct rte_gen *gen, + struct rte_mbuf **rx_pkts, + const uint16_t nb_pkts); + +/** Call to transmit a burst of traffic back to the generator. + * This allows the generator to calculate stats/properties of the stream. + * + * If the pkt_latencies parameter is not NULL, it is expected to be a pointer + * to an array of uint64_t values that has nb_pkts in length. Each individual + * packet latency will be stored to the array. + * + * @param gen + * Gen instance to be used. + * @param tx_pkts + * mbuf to be used to tx packets + * @param pkt_latencies + * Array to store latencies of sent packets + * @param nb_pkts + * The number of packets to be tx'ed + * + * @retval nb_pkts + * On success the number of packets tx'ed is returned + */ +__rte_experimental +uint16_t +rte_gen_tx_burst(struct rte_gen *gen, + struct rte_mbuf **tx_pkts, + uint64_t *pkt_latencies, + const uint16_t nb_pkts); + + #ifdef __cplusplus } #endif diff --git a/lib/gen/version.map b/lib/gen/version.map index d8a26eb53a..bdd25add6f 100644 --- a/lib/gen/version.map +++ b/lib/gen/version.map @@ -3,4 +3,6 @@ EXPERIMENTAL { rte_gen_create; rte_gen_destroy; + rte_gen_rx_burst; + rte_gen_tx_burst; }; From patchwork Fri Jan 21 10:31:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106166 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id F05A6A034E; Fri, 21 Jan 2022 11:32:02 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C311642764; Fri, 21 Jan 2022 11:31:39 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 2DB8C42757 for ; Fri, 21 Jan 2022 11:31:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761097; x=1674297097; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zncenptnen9fHq6YHxv55gRfhOol/tz/LC/EFi83TiM=; b=jaya3XRgG/tIOL5cBaY1AGCG7aG4KKCIRySezkR8JUBba2EHwKIFvgLm 9Vw+AljEd4O0fHe3NDhyg7eLGfzbOnFHvePzV6A3NqXX4OaYr7gGCYvqz 2ajVJ7jv2VyCAdoR9b3I8rGcctaq6idQgogXDZpaHPacCVOcJ8Iq3TVOs OByD8BRY9jWnWKLYyEtruX9Y+4+XDFV14b8tJ2QucKS9avhW1PcTYtDdx gWmWaDaofvEB3EfPJYoTX669Sw9yttOro/YPz/BN9U8lxbfjniu5ZFmH4 MqzSFaFX34SsFxmCin6c+IyClSbHfJIunxYiioqgg7J5PfAGRAagZc3ZM A==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045095" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045095" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:36 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222744" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:35 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren Subject: [PATCH v2 05/15] gen: add raw packet data API and tests Date: Fri, 21 Jan 2022 10:31:12 +0000 Message-Id: <20220121103122.2926856-6-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren This commit adds a new API to gen, allowing the caller to set raw packet data with a size. Tests are added to test the new API with randomized packet data. Signed-off-by: Harry van Haaren --- app/test/test_gen.c | 33 ++++++++++++++++++++++++ lib/gen/rte_gen.c | 62 +++++++++++++++++++++++++++++++++++++++++---- lib/gen/rte_gen.h | 9 +++++++ lib/gen/version.map | 1 + 4 files changed, 100 insertions(+), 5 deletions(-) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index ceacd8c7c4..b60ceaef8a 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "test.h" @@ -75,6 +76,37 @@ test_gen_loop_rxtx(void) total_sent += nb_tx; } + rte_gen_destroy(gen); + return 0; +} + +static int +test_gen_packet_set_raw(void) +{ + struct rte_gen *gen = rte_gen_create(mp); + TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); + + /* Set a raw packet payload, and ensure the next received packet has + * that packet data as contents and size. + */ + uint64_t pkt_data[8]; + uint32_t i; + for (i = 0; i < 8; i++) + pkt_data[i] = rte_rand(); + + int32_t err = rte_gen_packet_set_raw(gen, (void *)pkt_data, 64); + TEST_ASSERT_EQUAL(err, 0, "Expected set raw() to return success."); + + struct rte_mbuf *bufs[BURST_MAX]; + uint16_t nb_rx = rte_gen_rx_burst(gen, bufs, 1); + TEST_ASSERT_EQUAL(nb_rx, 1, "Expected rx packet burst."); + + void *mbuf_data = rte_pktmbuf_mtod(bufs[0], void *); + int32_t data_equal = memcmp(pkt_data, mbuf_data, 64) == 0; + TEST_ASSERT_EQUAL(data_equal, 1, + "Expected packet data equal to input data."); + + rte_pktmbuf_free(bufs[0]); rte_gen_destroy(gen); return 0; @@ -88,6 +120,7 @@ static struct unit_test_suite gen_suite = { TEST_CASE_ST(NULL, NULL, test_gen_create), TEST_CASE_ST(NULL, NULL, test_gen_basic_rxtx), TEST_CASE_ST(NULL, NULL, test_gen_loop_rxtx), + TEST_CASE_ST(NULL, NULL, test_gen_packet_set_raw), TEST_CASES_END() /**< NULL terminate unit test array */ } }; diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index f0ad57fa81..8a54c4bcdb 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -6,13 +6,25 @@ #include #include +#include +#include + +RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE); + +#define GEN_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, gen_logtype, "%s(): " fmt, \ + __func__, ## args) #define GEN_MAX_BURST 32 +#define GEN_INIT_PKT_SIZE 64 /** Structure that represents a traffic generator. */ struct rte_gen { /* Mempool that buffers are retrieved from. */ struct rte_mempool *mp; + + /* Packet template to send. */ + struct rte_mbuf *base_pkt; }; /* Allocate and initialize a traffic generator instance. */ @@ -25,6 +37,15 @@ rte_gen_create(struct rte_mempool *mempool) gen->mp = mempool; + uint8_t data[GEN_INIT_PKT_SIZE]; + memset(data, 0, GEN_INIT_PKT_SIZE); + int32_t err = rte_gen_packet_set_raw(gen, data, GEN_INIT_PKT_SIZE); + if (err) { + GEN_LOG(ERR, "Failed to set initial packet\n"); + rte_free(gen); + return NULL; + } + return gen; } @@ -32,9 +53,37 @@ rte_gen_create(struct rte_mempool *mempool) void rte_gen_destroy(struct rte_gen *gen) { + rte_pktmbuf_free(gen->base_pkt); rte_free(gen); } +int32_t +rte_gen_packet_set_raw(struct rte_gen *gen, + const uint8_t *raw_data, + uint32_t raw_data_size) +{ + + struct rte_mbuf *new_pkt = rte_pktmbuf_alloc(gen->mp); + if (!new_pkt) { + GEN_LOG(ERR, "Failed to retireve mbuf for parser\n"); + return -ENOMEM; + } + + uint8_t *base_data = rte_pktmbuf_mtod(new_pkt, uint8_t *); + new_pkt->pkt_len = raw_data_size; + new_pkt->data_len = raw_data_size; + rte_memcpy(base_data, raw_data, raw_data_size); + + /* If old packet exists, free it. */ + struct rte_mbuf *old_pkt = gen->base_pkt; + gen->base_pkt = new_pkt; + + if (old_pkt) + rte_pktmbuf_free(old_pkt); + + return 0; +} + uint16_t rte_gen_rx_burst(struct rte_gen *gen, struct rte_mbuf **rx_pkts, @@ -45,17 +94,20 @@ rte_gen_rx_burst(struct rte_gen *gen, if (err) return 0; - const uint32_t pkt_len = 64; + if (!gen->base_pkt) + return 0; + + const uint32_t base_size = gen->base_pkt->pkt_len; + const uint8_t *base_data = rte_pktmbuf_mtod(gen->base_pkt, uint8_t *); uint32_t i; for (i = 0; i < nb_pkts; i++) { struct rte_mbuf *m = rx_pkts[i]; uint8_t *pkt_data = rte_pktmbuf_mtod(m, uint8_t *); - memset(pkt_data, 0, pkt_len); - - m->pkt_len = pkt_len; - m->data_len = pkt_len; + rte_memcpy(pkt_data, base_data, base_size); + m->pkt_len = base_size; + m->data_len = base_size; } return nb_pkts; diff --git a/lib/gen/rte_gen.h b/lib/gen/rte_gen.h index 09ee1e8872..9119331673 100644 --- a/lib/gen/rte_gen.h +++ b/lib/gen/rte_gen.h @@ -85,6 +85,15 @@ rte_gen_tx_burst(struct rte_gen *gen, uint64_t *pkt_latencies, const uint16_t nb_pkts); +/* Update the packet being sent to the provided raw data. + * @retval 0 Success. + * @retval -ENOMEM No memory available. + */ +__rte_experimental +int32_t +rte_gen_packet_set_raw(struct rte_gen *gen, + const uint8_t *raw_data, + uint32_t raw_data_size); #ifdef __cplusplus } diff --git a/lib/gen/version.map b/lib/gen/version.map index bdd25add6f..d75e0b4bac 100644 --- a/lib/gen/version.map +++ b/lib/gen/version.map @@ -5,4 +5,5 @@ EXPERIMENTAL { rte_gen_destroy; rte_gen_rx_burst; rte_gen_tx_burst; + rte_gen_packet_set_raw; }; From patchwork Fri Jan 21 10:31:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106167 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 29CACA034E; Fri, 21 Jan 2022 11:32:09 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A908642769; Fri, 21 Jan 2022 11:31:40 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 069B842750 for ; Fri, 21 Jan 2022 11:31:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761098; x=1674297098; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=KE0FZUxIC5SRFTwuGuBQh2K25e6hNP4UWCCUUYxpKXo=; b=kdmo25cpRW3q6G3nlrS3FCWlh2ufkMZ5f2uBJhChQfNz5FlBOKmi17DJ o96DUjUOTakBhQpH+dIm0qCTlw1AryFBH27X0g7+9qv8zqwMk/sTjdkJ3 pdltrEsUPh17ZELGYPhJ93CLJj7uI5MLKxuilZ4skEiscgK7O0+dCGRm3 BVEg04sj4Tv3OGRi0jZ0u/2kj2FtYp0DYXtaJJlsMUBOUaEjgM2rAeo2V TJqyAis2CYu996uGCeLQb/bUogz9HKC/AjrDX4upJgNkebkSGQdYMR1Ub k/iAu0+HGUn8Z7jSn/cPk/xBX/XISwr2VxoLp5CIuHuIWfdd9IoW19xWi w==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045103" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045103" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:37 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222749" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:36 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren Subject: [PATCH v2 06/15] gen: add parsing infrastructure and Ether protocol Date: Fri, 21 Jan 2022 10:31:13 +0000 Message-Id: <20220121103122.2926856-7-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren This commit adds parsing infrastructure and support for Ether parsing. Appropriate unit tests are also added Signed-off-by: Harry van Haaren --- app/test/test_gen.c | 29 +++++ lib/gen/meson.build | 2 +- lib/gen/rte_gen.c | 299 ++++++++++++++++++++++++++++++++++++++++++++ lib/gen/rte_gen.h | 12 ++ lib/gen/version.map | 1 + 5 files changed, 342 insertions(+), 1 deletion(-) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index b60ceaef8a..324582d0a5 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -112,6 +112,34 @@ test_gen_packet_set_raw(void) return 0; } +static int +test_gen_packet_parse_string(void) +{ + struct rte_gen *gen = rte_gen_create(mp); + TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); + + struct str_parse_t { + const char *str; + } pkt_strings[] = { + { .str = "Ether()"}, + { .str = "Ether()/"}, + { .str = "/Ether()"}, + { .str = "/Ether()/"} + }; + + uint32_t i; + for (i = 0; i < RTE_DIM(pkt_strings); i++) { + const char *pkt_str = pkt_strings[i].str; + int32_t err = rte_gen_packet_parse_string(gen, pkt_str, NULL); + TEST_ASSERT_EQUAL(err, 0, "Expected string %s to parse.", + pkt_str); + } + + rte_gen_destroy(gen); + return 0; +} + + static struct unit_test_suite gen_suite = { .suite_name = "gen: packet generator unit test suite", .setup = testsuite_setup, @@ -121,6 +149,7 @@ static struct unit_test_suite gen_suite = { TEST_CASE_ST(NULL, NULL, test_gen_basic_rxtx), TEST_CASE_ST(NULL, NULL, test_gen_loop_rxtx), TEST_CASE_ST(NULL, NULL, test_gen_packet_set_raw), + TEST_CASE_ST(NULL, NULL, test_gen_packet_parse_string), TEST_CASES_END() /**< NULL terminate unit test array */ } }; diff --git a/lib/gen/meson.build b/lib/gen/meson.build index 753984cbba..b3a55564f4 100644 --- a/lib/gen/meson.build +++ b/lib/gen/meson.build @@ -3,4 +3,4 @@ sources = files('rte_gen.c') headers = files('rte_gen.h') -deps += ['mempool', 'mbuf'] +deps += ['mempool', 'mbuf', 'net'] diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index 8a54c4bcdb..4d3fe4017f 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -9,12 +9,18 @@ #include #include +#include + RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE); #define GEN_LOG(level, fmt, args...) \ rte_log(RTE_LOG_ ## level, gen_logtype, "%s(): " fmt, \ __func__, ## args) +/* Don't prefix with function name, breaks the Scapy style formatting. */ +#define GEN_LOG_PROTOCOL(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, gen_logtype, fmt, ## args) + #define GEN_MAX_BURST 32 #define GEN_INIT_PKT_SIZE 64 @@ -126,3 +132,296 @@ rte_gen_tx_burst(struct rte_gen *gen, return nb_pkts; } + +enum GEN_PROTO { + GEN_PROTO_INVALID, + GEN_PROTO_ETHER, + + /* Must be last. */ + GEN_PROTO_COUNT, +}; + +typedef void (*gen_log_func)(void *data, const char *indent); + +/* Structure for holding offset and function pointers for protocol. */ +struct protocol_meta { + /* Byte offset into packet where this protocol starts. */ + uint32_t offset; + /* Function to call to log the packet's information. */ + gen_log_func log_func; +}; + +/* Allow up to 32 nexted '/' characters in the protocol string. */ +#define GEN_PROTO_PARSE_MAX 16 + +/* Structure to hold state required while parsing. */ +struct gen_parser { + /* Mbuf the parsed data is being put into. */ + struct rte_mbuf *mbuf; + uint8_t *mbuf_data; + + /* Offset into the packet data to parse to next. */ + uint32_t buf_write_offset; + + /* Parsing state. */ + uint8_t parse_iter; + char indent_str[(GEN_PROTO_PARSE_MAX * 2) + 1]; + + /* String being parsed. */ + char *parse_string; + char *parse_strtok_save_ptr; + + /* Store metadata for parse/display of protocols. */ + struct protocol_meta proto_meta[GEN_PROTO_PARSE_MAX]; + + /* Per protocol hit counters. */ + uint32_t proto_hit_counters[GEN_PROTO_COUNT]; +}; + +/* Forward declaration of recursive parsing function. + * @param inner reports back the inner protocol that was handled. This is often + * required for the outer protocol to indicate what the inner protocol is. + */ +static int32_t +gen_parser_parse_next(struct gen_parser *parser, enum GEN_PROTO *inner); + +/* Return void pointer to the position in the data buffer to parse into. */ +static inline void * +gen_parser_get_data_ptr(struct gen_parser *parser) +{ + return &parser->mbuf_data[parser->buf_write_offset]; +} + +/* Initialize a parser structure. */ +static int32_t +gen_parser_init(struct gen_parser *parser, struct rte_gen *gen, + const char *pkt_string) +{ + /* Initialize own memory to zero. */ + memset(parser, 0, sizeof(*parser)); + + /* Duplicate string for tokenizing string. */ + parser->parse_string = strdup(pkt_string); + if (!parser->parse_string) + goto error; + + /* Allocate mbuf to parse packet into. */ + parser->mbuf = rte_pktmbuf_alloc(gen->mp); + if (!parser->mbuf) + goto error; + + parser->mbuf_data = rte_pktmbuf_mtod(parser->mbuf, uint8_t *); + + return 0; + +error: + free(parser->parse_string); + return -ENOMEM; +} + +static void +gen_log_ether(void *data, const char *indent) +{ + struct rte_ether_hdr *eth = data; + char src[64]; + char dst[64]; + + rte_ether_format_addr(src, 64, ð->src_addr); + rte_ether_format_addr(dst, 64, ð->dst_addr); + const char *type_str; + switch (rte_be_to_cpu_16(eth->ether_type)) { + case RTE_ETHER_TYPE_IPV4: + type_str = "IPv4"; + break; + default: + type_str = "0x9000"; + break; + }; + GEN_LOG_PROTOCOL(DEBUG, + "###[ Ethernet ]###\n%sdst= %s\n%ssrc= %s\n%stype= %s\n", + indent, dst, indent, src, indent, type_str); +} + +/* Ether(...) string detected, supports parameters: + * - dst : Destination MAC in 00:11:22:33:44:55 or 0011:2233:4455 forms. + * - src : Source MAC in the same forms. + * Note: + * - type is set based on the next header + */ +static int32_t +gen_parse_ether(struct gen_parser *parser, char *protocol_str) +{ + struct rte_ether_hdr *eth = gen_parser_get_data_ptr(parser); + + char *dst_ptr = strstr(protocol_str, "dst="); + if (dst_ptr) { + char *dup = strdup(dst_ptr); + rte_ether_unformat_addr(&dup[4], ð->dst_addr); + free(dup); + } else + rte_ether_unformat_addr("ff:ff:ff:ff:ff:ff", ð->dst_addr); + + char *src_ptr = strstr(protocol_str, "src="); + if (src_ptr) + rte_ether_unformat_addr(&src_ptr[4], ð->src_addr); + else + rte_ether_unformat_addr("00:00:00:00:00:00", ð->src_addr); + + /* Move up write pointer in packet. */ + parser->buf_write_offset += sizeof(*eth); + + /* Recurse and handle inner protocol. */ + enum GEN_PROTO inner; + int32_t err = gen_parser_parse_next(parser, &inner); + if (err) { + GEN_LOG(ERR, "parser parse next() error %d\n", err); + return err; + } + + switch (inner) { + default: + eth->ether_type = rte_cpu_to_be_16(0x9000); + break; + }; + return 0; +} + +/* (Name, Function-pointer) pairs for supported parse types */ +typedef int32_t (*gen_parse_func)(struct gen_parser *parser, + char *protocol_str); + +struct gen_parse_func_t { + const char *name; + enum GEN_PROTO proto; + gen_parse_func parse_func; + gen_log_func log_func; +}; + +/* Mapping from string to function to parse that protocol. */ +static struct gen_parse_func_t gen_protocols[] = { + { + .name = "Ether(", + .proto = GEN_PROTO_ETHER, + .parse_func = gen_parse_ether, + .log_func = gen_log_ether, + } +}; + +/* Function to tokenize and parse each segment of a string. + * @param outer indicates the protocol before this one. + * @param inner returns the protocol that is parsed here/now. + */ +static int32_t +gen_parser_parse_next(struct gen_parser *parser, + enum GEN_PROTO *inner_proto) +{ + /* Tokenize the input string based on '/' character. */ + char *tok_str = (parser->parse_iter == 0) ? + parser->parse_string : NULL; + parser->parse_string = strtok_r(tok_str, "/", + &parser->parse_strtok_save_ptr); + + /* End protocol parsing recursion when parse_string is NULL, or max + * protocol recursion depth is reached. + */ + if (!parser->parse_string || + parser->parse_iter >= GEN_PROTO_PARSE_MAX) { + struct rte_mbuf *mbuf = parser->mbuf; + mbuf->data_len = parser->buf_write_offset; + mbuf->pkt_len = parser->buf_write_offset; + GEN_LOG(DEBUG, "packet length %d\n", mbuf->pkt_len); + return 0; + } + + uint32_t i; + /* Loop over protocols, and identify the parse function to call. */ + for (i = 0; i < RTE_DIM(gen_protocols); i++) { + const char *proto = gen_protocols[i].name; + uint32_t proto_len = strlen(proto); + if (strncmp(proto, parser->parse_string, proto_len)) + continue; + + /* Store the log function pointer to output later. */ + uint32_t iter = parser->parse_iter; + parser->proto_hit_counters[i]++; + struct protocol_meta *meta = &parser->proto_meta[iter]; + + if (gen_protocols[i].log_func == NULL) { + GEN_LOG(ERR, "Missing log function, failed to log %s\n", + proto); + return -1; + } + meta->log_func = gen_protocols[i].log_func; + meta->offset = parser->buf_write_offset; + + if (gen_protocols[i].parse_func == NULL) { + GEN_LOG(ERR, "Missing parse function, failed to parse %s\n" + , proto); + return -1; + } + /* Handle protocol recursively. */ + parser->parse_iter++; + int err = gen_protocols[i].parse_func(parser, + parser->parse_string); + *inner_proto = gen_protocols[i].proto; + + return err; + } + + GEN_LOG(ERR, "parser does not understand protocol %s\n", + parser->parse_string); + return -1; +} + +int32_t +rte_gen_packet_parse_string(struct rte_gen *gen, + const char *pkt_string, + struct rte_mbuf **old_mbuf_to_user) +{ + struct gen_parser parser; + int32_t err = gen_parser_init(&parser, gen, pkt_string); + if (err) { + GEN_LOG(ERR, "error with parser_init(), %d\n", err); + return -1; + }; + + /* Recursively parse each protocol. */ + enum GEN_PROTO inner; + err = gen_parser_parse_next(&parser, &inner); + if (err) { + GEN_LOG(ERR, "Error in parsing packet string. " + "Set \"gen\" log level to debug for more info.\n"); + rte_pktmbuf_free(parser.mbuf); + return -1; + } + + uint32_t i; + /* Iterate the per protocol stored metadata to log output. */ + for (i = 0; i < parser.parse_iter; i++) { + snprintf(parser.indent_str, 2 + i * 2, + " " /* 32 spaces. */); + + if (gen_protocols[i].log_func == NULL) { + GEN_LOG(ERR, "Missing log function\n"); + return -1; + } + + void *buf_off = parser.mbuf_data + parser.proto_meta[i].offset; + parser.proto_meta[i].log_func(buf_off, parser.indent_str); + } + + if (inner != GEN_PROTO_ETHER) { + GEN_LOG(WARNING, + "Outer protocol of frame is not Ethernet.\n"); + } + + /* Free the currently in use mbuf. */ + if (old_mbuf_to_user) + *old_mbuf_to_user = gen->base_pkt; + else + rte_pktmbuf_free(gen->base_pkt); + + /* TODO: HVH design race-condition above vs rx/tx*/ + gen->base_pkt = parser.mbuf; + return 0; +} diff --git a/lib/gen/rte_gen.h b/lib/gen/rte_gen.h index 9119331673..93b3346436 100644 --- a/lib/gen/rte_gen.h +++ b/lib/gen/rte_gen.h @@ -95,6 +95,18 @@ rte_gen_packet_set_raw(struct rte_gen *gen, const uint8_t *raw_data, uint32_t raw_data_size); +/* Parse a string description of a packet. + * + * The optional out parameter supplies the previously being sent mbuf to + * the user to be freed later. If this argument is not provided, then the + * mbuf is freed by this function. + */ +__rte_experimental +int32_t +rte_gen_packet_parse_string(struct rte_gen *gen, + const char *pkt_string, + struct rte_mbuf **old_mbuf_to_user); + #ifdef __cplusplus } #endif diff --git a/lib/gen/version.map b/lib/gen/version.map index d75e0b4bac..e335c608ee 100644 --- a/lib/gen/version.map +++ b/lib/gen/version.map @@ -6,4 +6,5 @@ EXPERIMENTAL { rte_gen_rx_burst; rte_gen_tx_burst; rte_gen_packet_set_raw; + rte_gen_packet_parse_string; }; From patchwork Fri Jan 21 10:31:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106168 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9F0E0A034E; Fri, 21 Jan 2022 11:32:17 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E639A42771; Fri, 21 Jan 2022 11:31:41 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 4D3B742762 for ; Fri, 21 Jan 2022 11:31:39 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761099; x=1674297099; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RuPcIUsRTV2HJiGIyJKPAQE4R/HT7XW2d1NgMkWj6/Q=; b=hYtmLDIZFND9sOZpiYpIQgXUr8xqvAdXVv7SgT52/KrhsFlu/3ynPqQM DoOiCpIHxj3cNpQcm5ffIw6jGx951rnCljrPvMO3FVn+piszwOWzjYefZ KLiXVtYqIRIpU353Na0QMiiLcTMbkrJO+RYKi8Lsn2Y2cUttI0cglEkeG l86C2hTehvYh7/ompxhY+DKbvJu+J+KsdqDppxNbGtN0lBvQbtK8K1v/S 3xBaQbz2FXSqDa3pdyMELD7mFtms6HjCy/afdt6dRdq4PlbHGbgRIWNIJ OMcoFzS8IPXhLnLvtnhhZj+LgMJQzijeq3/KwkTBZP55416PjhVz0syS/ w==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045112" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045112" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:38 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222755" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:37 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren , Ronan Randles Subject: [PATCH v2 07/15] gen: add gen IP parsing Date: Fri, 21 Jan 2022 10:31:14 +0000 Message-Id: <20220121103122.2926856-8-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren This commit adds support for the parsing of "IP(src=...,dst=...)" strings. Parse string API improvement for app RCU. Appropriate unit tests also added. Signed-off-by: Harry van Haaren Signed-off-by: Ronan Randles --- app/test/test_gen.c | 29 +++++++-- lib/gen/rte_gen.c | 153 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 177 insertions(+), 5 deletions(-) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index 324582d0a5..7b67835c80 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -117,26 +117,47 @@ test_gen_packet_parse_string(void) { struct rte_gen *gen = rte_gen_create(mp); TEST_ASSERT_FAIL(gen, "Expected valid pointer after create()"); - struct str_parse_t { const char *str; + uint32_t expected_to_fail; } pkt_strings[] = { { .str = "Ether()"}, { .str = "Ether()/"}, { .str = "/Ether()"}, - { .str = "/Ether()/"} + { .str = "/Ether()/"}, + { .str = "Ether()/IP()"}, + { .str = "Ether()/IP(src=1.2.3.4,dst=5.6.7.8)"}, + { .str = "Ether()/IP(src=1.2.3.4,dst=192.168.255.255)"}, + { .str = "Ether()/IP(dst=172.16.0.9,src=1.2.3.4)"}, + { .str = "Ether()/IP(src=1.2.3.4)"}, + { .str = "Ether()/IP(srdst=5.6.7.8)", .expected_to_fail = 1}, + { .str = "Ether()/IP(src=1.2.3.4,ds=)", .expected_to_fail = 1}, + { .str = "Ether()/IP(src=1.2.3.4,dst=)", .expected_to_fail = 1}, + { .str = "Ether()/IP(src=,dst=5.6.7.8)", .expected_to_fail = 1}, + { .str = "Ether()/IP(sr=,dst=5.6.7.8)", .expected_to_fail = 1}, + { .str = "Ether()/IP(src=1.2.3.fail,dst=5.6.7.8)", + .expected_to_fail = 1}, }; uint32_t i; for (i = 0; i < RTE_DIM(pkt_strings); i++) { const char *pkt_str = pkt_strings[i].str; int32_t err = rte_gen_packet_parse_string(gen, pkt_str, NULL); - TEST_ASSERT_EQUAL(err, 0, "Expected string %s to parse.", - pkt_str); + + if (err && pkt_strings[i].expected_to_fail != 1) { + printf("Expected string %s to parse.", pkt_str); + return -1; + } + /* False pass if reached with no err when e_t_f = 1 */ + if (!err && pkt_strings[i].expected_to_fail) { + printf("False Pass on string: %s\n", pkt_str); + return -1; + } } rte_gen_destroy(gen); return 0; + } diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index 4d3fe4017f..4020150712 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -10,6 +10,7 @@ #include #include +#include RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE); @@ -136,6 +137,7 @@ rte_gen_tx_burst(struct rte_gen *gen, enum GEN_PROTO { GEN_PROTO_INVALID, GEN_PROTO_ETHER, + GEN_PROTO_IPV4, /* Must be last. */ GEN_PROTO_COUNT, @@ -219,6 +221,145 @@ gen_parser_init(struct gen_parser *parser, struct rte_gen *gen, return -ENOMEM; } +static void +gen_log_ipv4(void *data, const char *indent) +{ + struct rte_ipv4_hdr *ip = data; + + const char *proto_str; + switch (ip->next_proto_id) { + case 0: + proto_str = "hopopt"; + break; + default: + proto_str = "unknown next proto"; + break; + } + + GEN_LOG_PROTOCOL(DEBUG, + "###[ IP ]###\n%sversion = %d\n%sihl = %d\n%stos = %d\n" + "%slen = %d\n%sid = %d\n%sflags = 0x%x\n%sfrag = %d\n" + "%sttl = %d\n%sproto = %s (%d)\n%schksum 0x%x\n%ssrc = 0x%x\n" + "%sdst = 0x%x\n%soptions = %s\n", + indent, ip->version_ihl >> 4, + indent, ip->version_ihl & RTE_IPV4_HDR_IHL_MASK, + indent, ip->type_of_service, + indent, rte_be_to_cpu_16(ip->total_length), + indent, rte_be_to_cpu_16(ip->packet_id), /* TODO: Scapy ID? */ + indent, rte_be_to_cpu_16(ip->packet_id), /*TODO: Scapy Flags?*/ + indent, rte_be_to_cpu_16(ip->fragment_offset), + indent, ip->time_to_live, + indent, proto_str, ip->next_proto_id, + indent, rte_be_to_cpu_16(ip->hdr_checksum), + indent, rte_be_to_cpu_32(ip->src_addr), + indent, rte_be_to_cpu_32(ip->dst_addr), + indent, "notImplemented"); +} + +static int32_t +gen_parse_ipv4_params(char *protocol_str, struct rte_ipv4_hdr *ip) +{ + /* Strings to look for. */ + static const char * const items[] = { + "src=", + "dst=", + }; + const uint32_t num_items = RTE_DIM(items); + + char *tok_ptr; + uint32_t err = 0; + uint32_t i; + for (i = 0; i < num_items; i++) { + /* Print input string into local buffer for processing. */ + char buffer[1024]; + int chars_printed = snprintf(buffer, 1024, "%s", protocol_str); + if (chars_printed >= 1024) + return -1; + + /* Find substring (e.g. src=) if not found skip to next one. */ + char *start = strstr(buffer, items[i]); + char check_previous[32]; + if (start != NULL) { + snprintf(check_previous, 32, "%.1s", start - 1); + if (strcmp(&check_previous[0], "(") && + strcmp(&check_previous[0], ",")) + return -EINVAL; + } + + if (!start) { + if (!strstr(buffer, ",")) + continue; + else + return -EINVAL; + } + /* get from start of string till first , character. */ + char *item = strtok_r(start, ",", &tok_ptr); + + if (strcmp(item, items[i]) == 0) + return -EINVAL; + /* skip past the src= prefix. We know string is long enough as + * otherwise strstr() wouldn't have matched it. + */ + item = &item[4]; + + if (strcmp(items[i], "src=") == 0) { + err = rte_ip_parse_addr(item, &ip->src_addr); + ip->src_addr = rte_cpu_to_be_32(ip->src_addr); + } else { + err = rte_ip_parse_addr(item, &ip->dst_addr); + ip->dst_addr = rte_cpu_to_be_32(ip->dst_addr); + } + if (err) { + GEN_LOG(ERR, "parser ip_parse_addr error %d\n", err); + return err; + } + } + return 0; +} + +static int32_t +gen_parse_ipv4(struct gen_parser *parser, char *protocol_str) +{ + struct rte_ipv4_hdr *ip = gen_parser_get_data_ptr(parser); + uint32_t pre_ip_len = parser->buf_write_offset; + memset(ip, 0, sizeof(*ip)); + ip->version_ihl = RTE_IPV4_VHL_DEF; + ip->time_to_live = 64; + ip->packet_id = rte_cpu_to_be_16(1); + + /* default addrs */ + ip->src_addr = rte_cpu_to_be_32(RTE_IPV4(127, 0, 0, 1)); + ip->dst_addr = rte_cpu_to_be_32(RTE_IPV4(127, 0, 0, 1)); + + uint32_t err = 0; + if (strcmp("IP()", protocol_str)) + err = gen_parse_ipv4_params(protocol_str, ip); + + if (err) { + GEN_LOG(ERR, "parser parse ipv4 params error %d\n", err); + return err; + } + /* Move up write pointer in packet. */ + parser->buf_write_offset += sizeof(*ip); + + /* Move up write pointer in packet, recurse to next. */ + enum GEN_PROTO inner; + err = gen_parser_parse_next(parser, &inner); + if (err) { + GEN_LOG(ERR, "parser parse next() error %d\n", err); + return err; + } + + switch (inner) { + default: + /* Default protocol is hopopt (0). */ + break; + }; + + ip->total_length = rte_cpu_to_be_16(parser->mbuf->pkt_len - pre_ip_len); + return 0; +} + static void gen_log_ether(void *data, const char *indent) { @@ -279,6 +420,9 @@ gen_parse_ether(struct gen_parser *parser, char *protocol_str) } switch (inner) { + case GEN_PROTO_IPV4: + eth->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + break; default: eth->ether_type = rte_cpu_to_be_16(0x9000); break; @@ -304,7 +448,14 @@ static struct gen_parse_func_t gen_protocols[] = { .proto = GEN_PROTO_ETHER, .parse_func = gen_parse_ether, .log_func = gen_log_ether, - } + }, + { + .name = "IP(", + .proto = GEN_PROTO_IPV4, + .parse_func = gen_parse_ipv4, + .log_func = gen_log_ipv4, + }, + }; /* Function to tokenize and parse each segment of a string. From patchwork Fri Jan 21 10:31:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106169 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 90FC4A034E; Fri, 21 Jan 2022 11:32:23 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CEC3542778; Fri, 21 Jan 2022 11:31:42 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id CBC734276B for ; Fri, 21 Jan 2022 11:31:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761101; x=1674297101; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IIKYW+Z+43Ib9qY+rOCVzyISxAjcRPtzp3o2kDYSWf4=; b=gEF4M3jtHydWktW4FVEFVvuZE40nHMqiUuYqZ907H9FNogfDdxPDb2D6 /gF3FO5f4Ovo717RaG+OklXuRXUhiSUU37lJz0rHPIGGg4b4Nd9c/drPb LiljmhifjV9EhylDNi2TTvGviWh0yuBzWMsCXYFvQmRbvYeoksETbPdI9 Y1BPfC9oOJ55TKBX6FzNxHG+KAtDQYa1Jw2YPqYMb5isa2DKicdzp/YFn GBaZAaoWD1hwbmYVn28Y7pXNnfyacwK8tw0mNwHHm5wWab1KQWGJRixxv yXybOp+EIm0ymQq97qxWJH6dVnezy3YpoLiFgdrjp/D83R+69JbjbnXY0 g==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045115" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045115" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:40 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222763" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:38 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Harry van Haaren , Ronan Randles Subject: [PATCH v2 08/15] examples/generator: import code from basicfwd.c Date: Fri, 21 Jan 2022 10:31:15 +0000 Message-Id: <20220121103122.2926856-9-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Harry van Haaren Import files from basicfwd.c to act as starting point for gen library sample app Signed-off-by: Harry van Haaren Signed-off-by: Ronan Randles --- examples/generator/main.c | 226 +++++++++++++++++++++++++++++++++ examples/generator/meson.build | 12 ++ 2 files changed, 238 insertions(+) create mode 100644 examples/generator/main.c create mode 100644 examples/generator/meson.build diff --git a/examples/generator/main.c b/examples/generator/main.c new file mode 100644 index 0000000000..0082f588b4 --- /dev/null +++ b/examples/generator/main.c @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2015 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#define RX_RING_SIZE 1024 +#define TX_RING_SIZE 1024 + +#define NUM_MBUFS 8191 +#define MBUF_CACHE_SIZE 256 +#define BURST_SIZE 32 + +/* Configuration of ethernet ports. 8< */ +static const struct rte_eth_conf port_conf_default = { + .rxmode = { + .max_lro_pkt_size = RTE_ETHER_MAX_LEN, + }, +}; +/* >8 End of configuration of ethernet ports. */ + +/* basicfwd.c: Basic DPDK skeleton forwarding example. */ + +/* + * Initializes a given port using global settings and with the RX buffers + * coming from the mbuf_pool passed as a parameter. + */ + +/* Main functional part of port initialization. 8< */ +static inline int +port_init(uint16_t port, struct rte_mempool *mbuf_pool) +{ + struct rte_eth_conf port_conf = port_conf_default; + const uint16_t rx_rings = 1, tx_rings = 1; + uint16_t nb_rxd = RX_RING_SIZE; + uint16_t nb_txd = TX_RING_SIZE; + int retval; + uint16_t q; + struct rte_eth_dev_info dev_info; + struct rte_eth_txconf txconf; + + if (!rte_eth_dev_is_valid_port(port)) + return -1; + + retval = rte_eth_dev_info_get(port, &dev_info); + if (retval != 0) { + printf("Error during getting device (port %u) info: %s\n", + port, strerror(-retval)); + return retval; + } + + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) + port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + /* Configure the Ethernet device. */ + retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); + if (retval != 0) + return retval; + + retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); + if (retval != 0) + return retval; + + /* Allocate and set up 1 RX queue per Ethernet port. */ + for (q = 0; q < rx_rings; q++) { + retval = rte_eth_rx_queue_setup(port, q, nb_rxd, + rte_eth_dev_socket_id(port), NULL, mbuf_pool); + if (retval < 0) + return retval; + } + + txconf = dev_info.default_txconf; + txconf.offloads = port_conf.txmode.offloads; + /* Allocate and set up 1 TX queue per Ethernet port. */ + for (q = 0; q < tx_rings; q++) { + retval = rte_eth_tx_queue_setup(port, q, nb_txd, + rte_eth_dev_socket_id(port), &txconf); + if (retval < 0) + return retval; + } + + /* Starting Ethernet port. 8< */ + retval = rte_eth_dev_start(port); + /* >8 End of starting of ethernet port. */ + if (retval < 0) + return retval; + + /* Display the port MAC address. */ + struct rte_ether_addr addr; + retval = rte_eth_macaddr_get(port, &addr); + if (retval != 0) + return retval; + + printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 + " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", + port, RTE_ETHER_ADDR_BYTES(&addr)); + + /* Enable RX in promiscuous mode for the Ethernet device. */ + retval = rte_eth_promiscuous_enable(port); + /* End of setting RX port in promiscuous mode. */ + if (retval != 0) + return retval; + + return 0; +} +/* >8 End of main functional part of port initialization. */ + +/* + * The lcore main. This is the main thread that does the work, reading from + * an input port and writing to an output port. + */ + + /* Basic forwarding application lcore. 8< */ +static __rte_noreturn void +lcore_main(void) +{ + uint16_t port; + + /* + * Check that the port is on the same NUMA node as the polling thread + * for best performance. + */ + RTE_ETH_FOREACH_DEV(port) + if (rte_eth_dev_socket_id(port) >= 0 && + rte_eth_dev_socket_id(port) != + (int)rte_socket_id()) + printf("WARNING, port %u is on remote NUMA node to " + "polling thread.\n\tPerformance will " + "not be optimal.\n", port); + + printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", + rte_lcore_id()); + + /* Main work of application loop. 8< */ + for (;;) { + /* + * Receive packets on a port and forward them on the paired + * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. + */ + RTE_ETH_FOREACH_DEV(port) { + + /* Get burst of RX packets, from first port of pair. */ + struct rte_mbuf *bufs[BURST_SIZE]; + const uint16_t nb_rx = rte_eth_rx_burst(port, 0, + bufs, BURST_SIZE); + + if (unlikely(nb_rx == 0)) + continue; + + /* Send burst of TX packets, to second port of pair. */ + const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, + bufs, nb_rx); + + /* Free any unsent packets. */ + if (unlikely(nb_tx < nb_rx)) { + uint16_t buf; + for (buf = nb_tx; buf < nb_rx; buf++) + rte_pktmbuf_free(bufs[buf]); + } + } + } + /* >8 End of loop. */ +} +/* >8 End Basic forwarding application lcore. */ + +/* + * The main function, which does initialization and calls the per-lcore + * functions. + */ +int +main(int argc, char *argv[]) +{ + struct rte_mempool *mbuf_pool; + unsigned int nb_ports; + uint16_t portid; + + /* Initializion the Environment Abstraction Layer (EAL). 8< */ + int ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); + /* >8 End of initializion the Environment Abstraction Layer (EAL). */ + + argc -= ret; + argv += ret; + + /* Check that there is an even number of ports to send/receive on. */ + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports < 2 || (nb_ports & 1)) + rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); + + /* Creates a new mempool in memory to hold the mbufs. */ + + /* Allocates mempool to hold the mbufs. 8< */ + mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, + MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); + /* >8 End of allocating mempool to hold mbuf. */ + + if (mbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); + + /* Initializing all ports. 8< */ + RTE_ETH_FOREACH_DEV(portid) + if (port_init(portid, mbuf_pool) != 0) + rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", + portid); + /* >8 End of initializing all ports. */ + + if (rte_lcore_count() > 1) + printf("\nWARNING: Too many lcores enabled. Only 1 used.\n"); + + /* Call lcore_main on the main core only. Called on single lcore. 8< */ + lcore_main(); + /* >8 End of called on single lcore. */ + + /* clean up the EAL */ + rte_eal_cleanup(); + + return 0; +} diff --git a/examples/generator/meson.build b/examples/generator/meson.build new file mode 100644 index 0000000000..441678bbe5 --- /dev/null +++ b/examples/generator/meson.build @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +allow_experimental_apis = true +sources = files( + 'main.c', +) From patchwork Fri Jan 21 10:31:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106170 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D732CA0351; Fri, 21 Jan 2022 11:32:28 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B0C7742748; Fri, 21 Jan 2022 11:31:44 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 1E40942774 for ; Fri, 21 Jan 2022 11:31:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761102; x=1674297102; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VDRXKlWw9TRTNphmYTB+0xdMBmKXrbvRPs4qvhxRUvo=; b=cjPkImC/inAPybpV4jM8kkUyj0V4NFXo1hr2XFPoc22K6ODfrmA4A+t0 unZjyBWYHTWUuW+AgEYDngCLoNInFzCiSNh20rTjFqDxkLPT0xRC/zVJv KaN1Ml8XYxe60UFpQRWzblE6BUcZCxwN/7hSyqdP+3acI+LgM7BXAM82F FgCfbsnwfDZhOY2rEOs/0Hv2HfU2Vu4WSg85W2GTOETeC4j7pvrdvoXrq vl5y0MmjUsjNmeZMlISJpPxWptjyUl09Y7mTLAgxEAdsvoWiVGBs9tfm7 YcrvMFaCa0EtYdxJovISiElN7vJca58lpIkrFFsqH8jrOTF2gjDsdqbgE A==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045125" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045125" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222768" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:40 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 09/15] examples/generator: enable gen library for traffic gen Date: Fri, 21 Jan 2022 10:31:16 +0000 Message-Id: <20220121103122.2926856-10-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit shows the steps necessary to enable traffic generation using the gen library Signed-off-by: Ronan Randles --- examples/generator/main.c | 175 ++++++++++++++++++++++----------- examples/generator/meson.build | 1 + examples/meson.build | 1 + 3 files changed, 120 insertions(+), 57 deletions(-) diff --git a/examples/generator/main.c b/examples/generator/main.c index 0082f588b4..1ddf4c1603 100644 --- a/examples/generator/main.c +++ b/examples/generator/main.c @@ -1,14 +1,18 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2021 Intel Corporation */ #include #include +#include +#include + #include #include #include #include #include +#include #define RX_RING_SIZE 1024 #define TX_RING_SIZE 1024 @@ -16,23 +20,23 @@ #define NUM_MBUFS 8191 #define MBUF_CACHE_SIZE 256 #define BURST_SIZE 32 +#define MIN_THREADS 3 -/* Configuration of ethernet ports. 8< */ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_lro_pkt_size = RTE_ETHER_MAX_LEN, }, }; -/* >8 End of configuration of ethernet ports. */ -/* basicfwd.c: Basic DPDK skeleton forwarding example. */ +static volatile int done; +static struct rte_mempool *mbuf_pool; +struct rte_gen *gen; + +static void handle_sigint(int sig); -/* - * Initializes a given port using global settings and with the RX buffers +/* Initializes a given port using global settings and with the RX buffers * coming from the mbuf_pool passed as a parameter. */ - -/* Main functional part of port initialization. 8< */ static inline int port_init(uint16_t port, struct rte_mempool *mbuf_pool) { @@ -68,6 +72,12 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) if (retval != 0) return retval; + int lcore_available_count = rte_lcore_count(); + if (lcore_available_count < MIN_THREADS) { + printf("Not enough threads available\n"); + return -1; + } + /* Allocate and set up 1 RX queue per Ethernet port. */ for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, nb_rxd, @@ -86,9 +96,8 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) return retval; } - /* Starting Ethernet port. 8< */ + /* Start the Ethernet port. */ retval = rte_eth_dev_start(port); - /* >8 End of starting of ethernet port. */ if (retval < 0) return retval; @@ -104,27 +113,67 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) /* Enable RX in promiscuous mode for the Ethernet device. */ retval = rte_eth_promiscuous_enable(port); - /* End of setting RX port in promiscuous mode. */ if (retval != 0) return retval; return 0; } -/* >8 End of main functional part of port initialization. */ -/* - * The lcore main. This is the main thread that does the work, reading from +/* The lcore main. This is the main thread that does the work, reading from * an input port and writing to an output port. */ +static int +lcore_producer(__rte_unused void *arg) +{ + uint16_t port; + + /* Check that the port is on the same NUMA node as the polling thread + * for best performance. + */ + RTE_ETH_FOREACH_DEV(port) + if (rte_eth_dev_socket_id(port) >= 0 && + rte_eth_dev_socket_id(port) != + (int)rte_socket_id()) + printf("WARNING, port %u is on remote NUMA node to " + "polling thread.\n\tPerformance will " + "not be optimal.\n", port); - /* Basic forwarding application lcore. 8< */ -static __rte_noreturn void -lcore_main(void) + /* Run until the application is quit or killed. */ + while (!done) { + struct rte_mbuf *bufs[BURST_SIZE]; + int i; + /* Receive packets from gen and then tx them over port */ + RTE_ETH_FOREACH_DEV(port) { + int nb_recieved = rte_gen_rx_burst(gen, bufs, + BURST_SIZE); + for (i = 0; i < nb_recieved; i++) { + bufs[i]->pkt_len = 64; + bufs[i]->data_len = 64; + } + + uint16_t nb_tx = rte_eth_tx_burst(port, 0, bufs, + nb_recieved); + if (nb_tx != nb_recieved) + rte_pktmbuf_free_bulk(&bufs[nb_tx], + (nb_recieved - nb_tx)); + + if (unlikely(nb_tx == 0)) + continue; + + } + } + return 0; +} + +/* The lcore main. This is the main thread that does the work, reading from + * an input port and writing to an output port. + */ +static int +lcore_consumer(__rte_unused void *arg) { uint16_t port; - /* - * Check that the port is on the same NUMA node as the polling thread + /* Check that the port is on the same NUMA node as the polling thread * for best performance. */ RTE_ETH_FOREACH_DEV(port) @@ -135,57 +184,53 @@ lcore_main(void) "polling thread.\n\tPerformance will " "not be optimal.\n", port); - printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", - rte_lcore_id()); + /* Run until the application is quit or killed. */ + while (!done) { + struct rte_mbuf *bufs[BURST_SIZE]; - /* Main work of application loop. 8< */ - for (;;) { - /* - * Receive packets on a port and forward them on the paired - * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. + /* Receive packets over port and then tx them to gen library + * for stats */ RTE_ETH_FOREACH_DEV(port) { + uint64_t latency[BURST_SIZE]; + uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, + BURST_SIZE); + rte_gen_tx_burst(gen, bufs, latency, nb_rx); - /* Get burst of RX packets, from first port of pair. */ - struct rte_mbuf *bufs[BURST_SIZE]; - const uint16_t nb_rx = rte_eth_rx_burst(port, 0, - bufs, BURST_SIZE); + int nb_sent = rte_gen_tx_burst(gen, bufs, + latency, nb_rx); + if (nb_sent != nb_rx) + rte_panic("invalid tx quantity\n"); if (unlikely(nb_rx == 0)) continue; - /* Send burst of TX packets, to second port of pair. */ - const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, - bufs, nb_rx); - - /* Free any unsent packets. */ - if (unlikely(nb_tx < nb_rx)) { - uint16_t buf; - for (buf = nb_tx; buf < nb_rx; buf++) - rte_pktmbuf_free(bufs[buf]); - } } } - /* >8 End of loop. */ + return 0; } -/* >8 End Basic forwarding application lcore. */ -/* - * The main function, which does initialization and calls the per-lcore +void handle_sigint(int sig) +{ + RTE_SET_USED(sig); + printf("\nExiting...\n"); + done = 1; +} + +/* The main function, which does initialization and calls the per-lcore * functions. */ int main(int argc, char *argv[]) { - struct rte_mempool *mbuf_pool; + signal(SIGINT, handle_sigint); unsigned int nb_ports; uint16_t portid; - /* Initializion the Environment Abstraction Layer (EAL). 8< */ + /* Initialize the Environment Abstraction Layer (EAL). */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); - /* >8 End of initializion the Environment Abstraction Layer (EAL). */ argc -= ret; argv += ret; @@ -196,28 +241,44 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); /* Creates a new mempool in memory to hold the mbufs. */ - - /* Allocates mempool to hold the mbufs. 8< */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); - /* >8 End of allocating mempool to hold mbuf. */ if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); - /* Initializing all ports. 8< */ + /* Initialize all ports. */ RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); - /* >8 End of initializing all ports. */ - if (rte_lcore_count() > 1) - printf("\nWARNING: Too many lcores enabled. Only 1 used.\n"); + gen = rte_gen_create(mbuf_pool); + if (!gen) + rte_panic("Gen failed to initialize\n"); + + int err = rte_gen_packet_parse_string(gen, "Ether()/IP()", NULL); + if (err) + rte_panic("Failed to parse input args"); + + /* launch lcore functions */ + uint32_t lcore_count = 0; + uint32_t lcore_id = 0; + RTE_LCORE_FOREACH_WORKER(lcore_id) { + if (lcore_count == 0) + rte_eal_remote_launch(lcore_producer, NULL, lcore_id); + else if (lcore_count == 1) + rte_eal_remote_launch(lcore_consumer, NULL, lcore_id); + else + break; + + lcore_count++; + } + /* Stall the main thread until all other threads have returned. */ + rte_eal_mp_wait_lcore(); - /* Call lcore_main on the main core only. Called on single lcore. 8< */ - lcore_main(); - /* >8 End of called on single lcore. */ + /* All threads returned, safe to destroy gen instance */ + rte_gen_destroy(gen); /* clean up the EAL */ rte_eal_cleanup(); diff --git a/examples/generator/meson.build b/examples/generator/meson.build index 441678bbe5..15d84674a5 100644 --- a/examples/generator/meson.build +++ b/examples/generator/meson.build @@ -10,3 +10,4 @@ allow_experimental_apis = true sources = files( 'main.c', ) +deps += 'gen' \ No newline at end of file diff --git a/examples/meson.build b/examples/meson.build index 268422a257..c6765a151d 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -18,6 +18,7 @@ all_examples = [ 'fips_validation', 'flow_classify', 'flow_filtering', + 'generator', 'helloworld', 'ip_fragmentation', 'ip_pipeline', From patchwork Fri Jan 21 10:31:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106171 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7D371A034E; Fri, 21 Jan 2022 11:32:34 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A0B634277C; Fri, 21 Jan 2022 11:31:45 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 09DE842774 for ; Fri, 21 Jan 2022 11:31:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761103; x=1674297103; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=F6Cq19sqPEVqBmNbPNtO4MoAkwVlKA/xk1yLGbwzsxc=; b=iKf5o/gvW+8V2hMWhpYACyXbvtFlKuFrmyhlcr7g9BxCXsYrsr8Yf6US WSPqbAqQAJ+NlVUQ/jiqXR54gPae3zsgaX7Agsayjumj1EYIc3bA4yy4/ wme5x8W4efgCAnHCMdSxhLmJngJbe3ddRGZalZXed3RJDYPjqc8kW5+Dv FMcJPCtUkrm8DWHjE5JeMGixknZ3+NYzTgQk7D7wMfl6K4QU0fAs/aey1 feOZrBemGNnQjEBsl4t93lfr1jl9rTvXKBpkX6bPlbjfVf69v5pvdS5Da GBeDhxzeXSrrt4+pus4/Hu/G+bX/sPDfnRc08OA2gykqtHDH5YgX2vAof w==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045131" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045131" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222772" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:41 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 10/15] examples/generator: telemetry support Date: Fri, 21 Jan 2022 10:31:17 +0000 Message-Id: <20220121103122.2926856-11-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit adds telemetry introducing the callback functions and returning measured values Signed-off-by: Ronan Randles --- examples/generator/main.c | 142 +++++++++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 24 deletions(-) diff --git a/examples/generator/main.c b/examples/generator/main.c index 1ddf4c1603..1ac3caafcc 100644 --- a/examples/generator/main.c +++ b/examples/generator/main.c @@ -13,6 +13,7 @@ #include #include #include +#include #define RX_RING_SIZE 1024 #define TX_RING_SIZE 1024 @@ -32,6 +33,27 @@ static volatile int done; static struct rte_mempool *mbuf_pool; struct rte_gen *gen; +struct gen_args { + /* Inputs */ + struct rte_gen *gen; + + /* Outputs */ + uint64_t tx_total_packets; + uint64_t rx_total_packets; + uint64_t rx_missed_total; + uint64_t tx_failed; + uint64_t last_tx_total; + uint64_t measured_tx_pps; +} __rte_cache_aligned; +/* Expose a struct as a global so the telemetry callbacks can access the + * data required to provide stats etc. + */ +struct telemetry_userdata { + struct gen_args *prod; + struct gen_args *cons; +}; +static struct telemetry_userdata telemetry_userdata; + static void handle_sigint(int sig); /* Initializes a given port using global settings and with the RX buffers @@ -123,10 +145,11 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) * an input port and writing to an output port. */ static int -lcore_producer(__rte_unused void *arg) +lcore_producer(void *arg) { + struct gen_args *args = arg; + struct rte_gen *gen = args->gen; uint16_t port; - /* Check that the port is on the same NUMA node as the polling thread * for best performance. */ @@ -138,25 +161,34 @@ lcore_producer(__rte_unused void *arg) "polling thread.\n\tPerformance will " "not be optimal.\n", port); + uint64_t tsc_hz = rte_get_tsc_hz(); + uint64_t last_tsc_reading = 0; + uint64_t last_tx_total = 0; + /* Run until the application is quit or killed. */ while (!done) { struct rte_mbuf *bufs[BURST_SIZE]; - int i; + uint16_t nb_tx = 0; /* Receive packets from gen and then tx them over port */ RTE_ETH_FOREACH_DEV(port) { - int nb_recieved = rte_gen_rx_burst(gen, bufs, + int nb_generated = rte_gen_rx_burst(gen, bufs, BURST_SIZE); - for (i = 0; i < nb_recieved; i++) { - bufs[i]->pkt_len = 64; - bufs[i]->data_len = 64; - } - uint16_t nb_tx = rte_eth_tx_burst(port, 0, bufs, - nb_recieved); - if (nb_tx != nb_recieved) - rte_pktmbuf_free_bulk(&bufs[nb_tx], - (nb_recieved - nb_tx)); + uint64_t start_tsc = rte_rdtsc(); + if (start_tsc > last_tsc_reading + tsc_hz) { + args->measured_tx_pps = args->tx_total_packets - + last_tx_total; + last_tx_total = args->tx_total_packets; + last_tsc_reading = start_tsc; + } + nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_generated); + args->tx_total_packets += nb_tx; + uint64_t tx_failed = nb_generated - nb_tx; + if (nb_tx != nb_generated) { + rte_pktmbuf_free_bulk(&bufs[nb_tx], tx_failed); + args->tx_failed += tx_failed; + } if (unlikely(nb_tx == 0)) continue; @@ -169,10 +201,11 @@ lcore_producer(__rte_unused void *arg) * an input port and writing to an output port. */ static int -lcore_consumer(__rte_unused void *arg) +lcore_consumer(void *arg) { + struct gen_args *args = arg; + struct rte_gen *gen = args->gen; uint16_t port; - /* Check that the port is on the same NUMA node as the polling thread * for best performance. */ @@ -195,16 +228,16 @@ lcore_consumer(__rte_unused void *arg) uint64_t latency[BURST_SIZE]; uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); - rte_gen_tx_burst(gen, bufs, latency, nb_rx); + if (unlikely(nb_rx == 0)) + continue; + + args->rx_total_packets += nb_rx; int nb_sent = rte_gen_tx_burst(gen, bufs, latency, nb_rx); if (nb_sent != nb_rx) rte_panic("invalid tx quantity\n"); - if (unlikely(nb_rx == 0)) - continue; - } } return 0; @@ -217,6 +250,45 @@ void handle_sigint(int sig) done = 1; } +static int +tele_gen_mpps(const char *cmd, const char *params, struct rte_tel_data *d) +{ + RTE_SET_USED(cmd); + RTE_SET_USED(params); + + struct gen_args *args = telemetry_userdata.prod; + rte_tel_data_start_dict(d); + rte_tel_data_add_dict_int(d, "pps", + (args->measured_tx_pps)); + return 0; +} + +static int +tele_gen_stats(const char *cmd, const char *params, struct rte_tel_data *d) +{ + RTE_SET_USED(cmd); + RTE_SET_USED(params); + + struct gen_args *args_prod = telemetry_userdata.prod; + struct gen_args *args_cons = telemetry_userdata.cons; + rte_tel_data_start_dict(d); + static const char * const stats[] = { + "tx_total_packets", + "rx_total_packets", + "measured_tx_pps" + }; + + uint64_t values[RTE_DIM(stats)] = {0}; + values[0] = args_prod->tx_total_packets; + values[1] = args_cons->rx_total_packets; + values[2] = args_prod->measured_tx_pps; + + uint32_t i; + for (i = 0; i < RTE_DIM(stats); i++) + rte_tel_data_add_dict_int(d, stats[i], values[i]); + + return 0; +} /* The main function, which does initialization and calls the per-lcore * functions. */ @@ -224,6 +296,10 @@ int main(int argc, char *argv[]) { signal(SIGINT, handle_sigint); + + #define CORE_COUNT 2 + struct gen_args core_launch_args[CORE_COUNT]; + unsigned int nb_ports; uint16_t portid; @@ -253,7 +329,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); - gen = rte_gen_create(mbuf_pool); + struct rte_gen *gen = rte_gen_create(mbuf_pool); if (!gen) rte_panic("Gen failed to initialize\n"); @@ -261,19 +337,37 @@ main(int argc, char *argv[]) if (err) rte_panic("Failed to parse input args"); + memset(core_launch_args, 0, sizeof(struct gen_args) * CORE_COUNT); /* launch lcore functions */ uint32_t lcore_count = 0; uint32_t lcore_id = 0; RTE_LCORE_FOREACH_WORKER(lcore_id) { - if (lcore_count == 0) - rte_eal_remote_launch(lcore_producer, NULL, lcore_id); - else if (lcore_count == 1) - rte_eal_remote_launch(lcore_consumer, NULL, lcore_id); + core_launch_args[lcore_count].gen = gen; + if (lcore_count == 0) { + telemetry_userdata.prod = + &core_launch_args[lcore_count]; + rte_eal_remote_launch(lcore_producer, + telemetry_userdata.prod, + lcore_id); + } else if (lcore_count == 1) { + telemetry_userdata.cons = + &core_launch_args[lcore_count]; + rte_eal_remote_launch(lcore_consumer, + telemetry_userdata.cons, + lcore_id); + } else break; lcore_count++; } + + /* Export stats via Telemetry */ + rte_telemetry_register_cmd("/gen/stats", tele_gen_stats, + "Return statistics of the Gen instance."); + rte_telemetry_register_cmd("/gen/mpps", tele_gen_mpps, + "Get/Set the mpps rate"); + /* Stall the main thread until all other threads have returned. */ rte_eal_mp_wait_lcore(); From patchwork Fri Jan 21 10:31:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106172 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A2F06A034E; Fri, 21 Jan 2022 11:32:41 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C804C42786; Fri, 21 Jan 2022 11:31:46 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 005E440042 for ; Fri, 21 Jan 2022 11:31:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761104; x=1674297104; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8LhZfzmp2EezJLVPdCKhcaxDJb9I56S7MDmCLyZtqZc=; b=JXshPH6vKC2Pe7GIO5Pf18el9MBUPTk6Q4eQ9dpmzbV9qIV15VfwoBid jFCXMRRu1Qh6yjz1AecGQF43AKO6a4MihkuOZ6dR363PpcCbDLffYXzMF VrpWFiRDjOFqdsJScFvr8uwI9pCL3jb+UJa2erxFT+8ybU4vv+RbIESGR ctShyVQfs9zauFPVyLlsTiOhFgkAxqnYAoNpt/Dop9Fn1NrTOZpPB1gky K69/bJQD96R3sYUJHSBvKkpq334XevSlbT1HVwZX7xkemvKy71VFGTDtZ mefpkwzIQRv32NkHU+zwhzvQZJ/bFjjjXxFPwDpqNuKaqtGnoEYDHUOHT Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045136" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045136" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:43 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222780" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:42 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 11/15] examples/generator: link status check added Date: Fri, 21 Jan 2022 10:31:18 +0000 Message-Id: <20220121103122.2926856-12-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit brings in a link status check so that the generator will only start sending packets once there is something on the other end of the link. Signed-off-by: Ronan Randles --- examples/generator/main.c | 68 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/examples/generator/main.c b/examples/generator/main.c index 1ac3caafcc..0834a094a4 100644 --- a/examples/generator/main.c +++ b/examples/generator/main.c @@ -27,9 +27,13 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_lro_pkt_size = RTE_ETHER_MAX_LEN, }, + .intr_conf = { + .lsc = 1, /**< lsc interrupt */ + }, }; static volatile int done; +static volatile int link_status[RTE_MAX_ETHPORTS]; static struct rte_mempool *mbuf_pool; struct rte_gen *gen; @@ -56,6 +60,30 @@ static struct telemetry_userdata telemetry_userdata; static void handle_sigint(int sig); +static int +link_status_change_cb(uint16_t port_id, enum rte_eth_event_type type, + void *param, void *ret_param) +{ + if (unlikely(port_id >= RTE_DIM(link_status))) + rte_panic("got LSC interrupt for unknown port id\n"); + + RTE_SET_USED(type); + RTE_SET_USED(param); + RTE_SET_USED(ret_param); + + struct rte_eth_link link; + int ret = rte_eth_link_get_nowait(port_id, &link); + if (ret < 0) { + printf("Failed link get on port %d: %s\n", + port_id, rte_strerror(-ret)); + return ret; + } + + printf("Link status change port %i\n", port_id); + link_status[port_id] = link.link_status; + return 0; +} + /* Initializes a given port using global settings and with the RX buffers * coming from the mbuf_pool passed as a parameter. */ @@ -99,6 +127,9 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) printf("Not enough threads available\n"); return -1; } + /* Register the LinkStatusChange callback */ + rte_eth_dev_callback_register(port, RTE_ETH_EVENT_INTR_LSC, + link_status_change_cb, NULL); /* Allocate and set up 1 RX queue per Ethernet port. */ for (q = 0; q < rx_rings; q++) { @@ -138,9 +169,33 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) if (retval != 0) return retval; + struct rte_eth_link link; + int ret = rte_eth_link_get_nowait(port, &link); + if (ret < 0) { + printf("Failed link get on port %d: %s\n", port, + rte_strerror(-ret)); + return ret; + } + + link_status[port] = link.link_status; + return 0; } +static void +gen_wait_for_links_up(void) +{ + /* Ensure all available ports are up before generating packets */ + uint16_t nb_eth_ports = rte_eth_dev_count_avail(); + uint16_t nb_links_up = 0; + while (!done && nb_links_up < nb_eth_ports) { + if (link_status[nb_links_up]) + nb_links_up++; + + rte_delay_us_block(100); + } +} + /* The lcore main. This is the main thread that does the work, reading from * an input port and writing to an output port. */ @@ -164,12 +219,19 @@ lcore_producer(void *arg) uint64_t tsc_hz = rte_get_tsc_hz(); uint64_t last_tsc_reading = 0; uint64_t last_tx_total = 0; + uint16_t nb_tx = 0; + + /* Wait for links to come up before generating packets */ + gen_wait_for_links_up(); + if (!done) + printf("Generating packets...\n"); /* Run until the application is quit or killed. */ while (!done) { + struct rte_mbuf *bufs[BURST_SIZE]; - uint16_t nb_tx = 0; /* Receive packets from gen and then tx them over port */ + RTE_ETH_FOREACH_DEV(port) { int nb_generated = rte_gen_rx_burst(gen, bufs, BURST_SIZE); @@ -217,8 +279,12 @@ lcore_consumer(void *arg) "polling thread.\n\tPerformance will " "not be optimal.\n", port); + /* Wait for links to come up before generating packets */ + gen_wait_for_links_up(); + /* Run until the application is quit or killed. */ while (!done) { + struct rte_mbuf *bufs[BURST_SIZE]; /* Receive packets over port and then tx them to gen library From patchwork Fri Jan 21 10:31:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106173 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id CB91CA034E; Fri, 21 Jan 2022 11:32:46 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B859F4278B; Fri, 21 Jan 2022 11:31:47 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 7514C4276D for ; Fri, 21 Jan 2022 11:31:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761105; x=1674297105; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hbr2QB5kWiIwic2mWUsqcJy2y20Exh2SVWo0bnRLpa4=; b=THRX3bNt9iAEfx7g35dqGt/fCAlmwU8oT8XamLXgyW9MVqAvXW6iLaye CpYRDkIxCRPLy7k0B9erHgpgRNhD0c3Z+Z12FubmbDviDezcvoQixjOp/ 7nHTCHlOC+Up9atFKFOaA3Jp+ppdDb/UM3XAdEaQfEK8YvRS579eqMWLt YtTUEe/CxYwu74q0MfcHzCoeUvRVzggsRTp6NxqwjCNcdGPNDeLB5edZw 1Otzc52idttxmv1p1CHE65NIBFEt6M1/YKMTIDzyNBbl4zXXOQloDYNw9 hVXv902UJuqMMWNFovWkECw1idhC/5oX7gaWlAizEpQDw0B+RMcgnh+Zv Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045140" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045140" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:44 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222785" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:43 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 12/15] examples/generator: line rate limiting Date: Fri, 21 Jan 2022 10:31:19 +0000 Message-Id: <20220121103122.2926856-13-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit introduces line rate limiting using a token passing method. The target traffic rate default is currently hard coded, this can be set using telemetry. Signed-off-by: Ronan Randles --- examples/generator/main.c | 79 +++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/examples/generator/main.c b/examples/generator/main.c index 0834a094a4..16292f06db 100644 --- a/examples/generator/main.c +++ b/examples/generator/main.c @@ -40,6 +40,7 @@ struct rte_gen *gen; struct gen_args { /* Inputs */ struct rte_gen *gen; + uint64_t target_tx_pps; /* Outputs */ uint64_t tx_total_packets; @@ -195,7 +196,6 @@ gen_wait_for_links_up(void) rte_delay_us_block(100); } } - /* The lcore main. This is the main thread that does the work, reading from * an input port and writing to an output port. */ @@ -217,43 +217,63 @@ lcore_producer(void *arg) "not be optimal.\n", port); uint64_t tsc_hz = rte_get_tsc_hz(); + float tsc_hz_f = (float)tsc_hz; uint64_t last_tsc_reading = 0; uint64_t last_tx_total = 0; uint16_t nb_tx = 0; + float tokens = 0; /* Wait for links to come up before generating packets */ gen_wait_for_links_up(); if (!done) printf("Generating packets...\n"); + uint64_t token_last_add_tsc = rte_rdtsc(); + /* Run until the application is quit or killed. */ while (!done) { - struct rte_mbuf *bufs[BURST_SIZE]; - /* Receive packets from gen and then tx them over port */ - - RTE_ETH_FOREACH_DEV(port) { - int nb_generated = rte_gen_rx_burst(gen, bufs, - BURST_SIZE); - - uint64_t start_tsc = rte_rdtsc(); - if (start_tsc > last_tsc_reading + tsc_hz) { - args->measured_tx_pps = args->tx_total_packets - - last_tx_total; - last_tx_total = args->tx_total_packets; - last_tsc_reading = start_tsc; + /* Track time since last token add and calculate number + * of tokens to give per second to implement line rate limiting + */ + uint64_t now = rte_rdtsc(); + uint64_t tsc_delta = now - token_last_add_tsc; + float token_scalar = (float)tsc_delta / tsc_hz_f; + float add_tokens = args->target_tx_pps * token_scalar; + /* If there are tokens to be added and we haven't exceeded + * the target rate then we add tokens + */ + if (add_tokens > 1.f) { + if (tokens < args->target_tx_pps) { + tokens += add_tokens; + token_last_add_tsc = now; } - nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_generated); - args->tx_total_packets += nb_tx; - - uint64_t tx_failed = nb_generated - nb_tx; - if (nb_tx != nb_generated) { - rte_pktmbuf_free_bulk(&bufs[nb_tx], tx_failed); - args->tx_failed += tx_failed; + } + /* Receive packets from gen and then tx them over port */ + if (tokens >= BURST_SIZE) { + RTE_ETH_FOREACH_DEV(port) { + int nb_generated = rte_gen_rx_burst(gen, bufs, + BURST_SIZE); + + uint64_t start_tsc = rte_rdtsc(); + if (start_tsc > last_tsc_reading + tsc_hz) { + args->measured_tx_pps = + args->tx_total_packets - last_tx_total; + last_tx_total = args->tx_total_packets; + last_tsc_reading = start_tsc; + } + nb_tx = rte_eth_tx_burst(port, 0, bufs, + nb_generated); + args->tx_total_packets += nb_tx; + tokens -= nb_tx; + + uint64_t tx_failed = nb_generated - nb_tx; + if (nb_tx != nb_generated) { + rte_pktmbuf_free_bulk(&bufs[nb_tx], + tx_failed); + args->tx_failed += tx_failed; + } } - if (unlikely(nb_tx == 0)) - continue; - } } return 0; @@ -296,7 +316,6 @@ lcore_consumer(void *arg) BURST_SIZE); if (unlikely(nb_rx == 0)) continue; - args->rx_total_packets += nb_rx; int nb_sent = rte_gen_tx_burst(gen, bufs, @@ -320,12 +339,14 @@ static int tele_gen_mpps(const char *cmd, const char *params, struct rte_tel_data *d) { RTE_SET_USED(cmd); - RTE_SET_USED(params); struct gen_args *args = telemetry_userdata.prod; + if (params) { + args->target_tx_pps = atoi(params) * 1000000; + printf("Packet rate set: %li\n", args->target_tx_pps); + } rte_tel_data_start_dict(d); - rte_tel_data_add_dict_int(d, "pps", - (args->measured_tx_pps)); + rte_tel_data_add_dict_int(d, "pps", args->target_tx_pps); return 0; } @@ -412,6 +433,8 @@ main(int argc, char *argv[]) if (lcore_count == 0) { telemetry_userdata.prod = &core_launch_args[lcore_count]; + /* Default traffic rate */ + telemetry_userdata.prod->target_tx_pps = 20000000; rte_eal_remote_launch(lcore_producer, telemetry_userdata.prod, lcore_id); From patchwork Fri Jan 21 10:31:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106174 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C35BCA034E; Fri, 21 Jan 2022 11:32:51 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9243042790; Fri, 21 Jan 2022 11:31:48 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 4A5894276D for ; Fri, 21 Jan 2022 11:31:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761106; x=1674297106; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=I9mkbkSBoHMIpIQwsuTaEYY/J5xcaK64aU5xNJNJb4w=; b=PE3vCpcAKvaIqdGOFGmo8uId9hawea8HVn/wad8b6iBYEfpTq/Y1b3ux PHjOqaV5cy4zrCKiDnKULH8eeJ+xASqhPfT1ZfpM60KSkWcYK7Q2kTFGO /g6vxWok3ONWrPFruxPgKsH1+ganxwvrFDsFRg0Cbn4C7m5di/nrk1htO 1qFRX6mmLm7B0tfABKozXfK5qrv92Ve6vo/fVI/9PBzqYEttkNhXiWQ89 E/hjd3olVgI1Keb6hptcZGHaBt1Rp4B5Tkfj24VMUQjgpC7RuH6CifWad KJ55cWVnb5o3Q5aQw4zFEn1LDdV4r2HuDmnTMfoaKPGdNmtI/e8OJNq2a g==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045145" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045145" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222789" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:44 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 13/15] gen: add UDP support Date: Fri, 21 Jan 2022 10:31:20 +0000 Message-Id: <20220121103122.2926856-14-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit adds UDP parsing and logging. Unit tested by the adition of "UDP()" string to 'test_gen_packet_parse_string()' Signed-off-by: Ronan Randles --- app/test/test_gen.c | 1 + lib/gen/rte_gen.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index 7b67835c80..a0b00d6a6e 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -137,6 +137,7 @@ test_gen_packet_parse_string(void) { .str = "Ether()/IP(sr=,dst=5.6.7.8)", .expected_to_fail = 1}, { .str = "Ether()/IP(src=1.2.3.fail,dst=5.6.7.8)", .expected_to_fail = 1}, + { .str = "Ether()/IP()/UDP()"}, }; uint32_t i; diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index 4020150712..3a67ce8b6c 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -11,6 +11,7 @@ #include #include +#include RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE); @@ -138,6 +139,7 @@ enum GEN_PROTO { GEN_PROTO_INVALID, GEN_PROTO_ETHER, GEN_PROTO_IPV4, + GEN_PROTO_UDP, /* Must be last. */ GEN_PROTO_COUNT, @@ -231,6 +233,9 @@ gen_log_ipv4(void *data, const char *indent) case 0: proto_str = "hopopt"; break; + case IPPROTO_UDP: + proto_str = "UDP"; + break; default: proto_str = "unknown next proto"; break; @@ -351,6 +356,12 @@ gen_parse_ipv4(struct gen_parser *parser, char *protocol_str) } switch (inner) { + case GEN_PROTO_UDP: + ip->next_proto_id = IPPROTO_UDP; + struct rte_udp_hdr *udp = gen_parser_get_data_ptr(parser); + udp->dgram_cksum = 0; + break; + default: /* Default protocol is hopopt (0). */ break; @@ -430,6 +441,55 @@ gen_parse_ether(struct gen_parser *parser, char *protocol_str) return 0; } +static void +gen_log_udp(void *data, const char *indent) +{ + struct rte_udp_hdr *udp = data; + + GEN_LOG_PROTOCOL(DEBUG, + "###[ UDP ]###\n%ssport= %u\n%sdport= %u\n%s" + "len= %u\n%schksum= %u\n", + indent, rte_be_to_cpu_16(udp->src_port), + indent, rte_be_to_cpu_16(udp->dst_port), + indent, rte_be_to_cpu_16(udp->dgram_len), + indent, rte_be_to_cpu_16(udp->dgram_cksum)); + +} + +static int32_t +gen_parse_udp(struct gen_parser *parser, char *protocol_str) +{ + RTE_SET_USED(protocol_str); + struct rte_udp_hdr *udp = gen_parser_get_data_ptr(parser); + uint32_t pre_udp_len = parser->buf_write_offset; + memset(udp, 0, sizeof(*udp)); + + /* Move up write pointer in packet. */ + parser->buf_write_offset += sizeof(*udp); + + /* Recurse and handle inner protocol. */ + enum GEN_PROTO inner; + int err = gen_parser_parse_next(parser, &inner); + + switch (inner) { + default: + /* default to DNS like other packet generation tools */ + udp->src_port = rte_cpu_to_be_16(53); + udp->dst_port = rte_cpu_to_be_16(53); + break; + }; + + /* Minimum len is the UDP header itself (8 bytes) or more */ + int32_t total_len = parser->mbuf->data_len; + int32_t dgram_len = total_len - pre_udp_len; + if (dgram_len < 8) + printf("error parsing dgram len, %d\n", dgram_len); + + udp->dgram_len = rte_cpu_to_be_16(dgram_len); + + return err; +} + /* (Name, Function-pointer) pairs for supported parse types */ typedef int32_t (*gen_parse_func)(struct gen_parser *parser, char *protocol_str); @@ -455,6 +515,12 @@ static struct gen_parse_func_t gen_protocols[] = { .parse_func = gen_parse_ipv4, .log_func = gen_log_ipv4, }, + { + .name = "UDP(", + .proto = GEN_PROTO_UDP, + .parse_func = gen_parse_udp, + .log_func = gen_log_udp, + } }; From patchwork Fri Jan 21 10:31:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106175 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C6F70A034E; Fri, 21 Jan 2022 11:32:56 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7751E42794; Fri, 21 Jan 2022 11:31:49 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 96A8942780 for ; Fri, 21 Jan 2022 11:31:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761107; x=1674297107; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=KJD9CFYwks2bpcX/wrPxN00yUIJ0KagbgTrqNWaax+Y=; b=KuqU+CRAN6xSwHvG8VJaxuCH3BVfsNCnXD9IaqwCtL4jZADqFXWKGEmR tKl9XYvbWvYg579xyP2ie3S609oV9/FbWoIdlYkILxXFghxLuNDjJsQCm NBV0LVCjJ/kMuiJsQIVd9imjgnnvvVj7AqmGKINhYcrn6Rn0WbDWxUBk/ TYzPyGgdDcercFDwsrh7AgijIwnt/ZvH5PsQHqgVWurqgzRVsCKw0T7Sg NPiPGvwz4xHsJTQp1R8zrrQU61Ib9NFA2raopomuTQ7/sGdkKSpa5fMSH eI01hsbSrdnzY0E5FuHTaR9fpv6bRWgfEigXKBlEOT5DDN6tKuCEDzdg8 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045152" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045152" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222795" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:45 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 14/15] net/vxlan: instance flag endianness refactored Date: Fri, 21 Jan 2022 10:31:21 +0000 Message-Id: <20220121103122.2926856-15-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This patch improves the setting of the instance flag in the rte_vxlan_hdr struct, by using a byte to represent vx_flag_bits. Previously it was exposed to the user via a rte_be32_t value, which required handling endianness at the application level. The code uses a union to ensure that existing code continues to work as before, while allowing the improved more usable method to co-exist. A new #define is introduced to represent the instance bit, which must be set if a vxlan header contains a valid VNI field, see https://datatracker.ietf.org/doc/html/rfc7348 for details Signed-off-by: Ronan Randles --- lib/net/rte_vxlan.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/net/rte_vxlan.h b/lib/net/rte_vxlan.h index 929fa7a1dd..86b6d8a3ae 100644 --- a/lib/net/rte_vxlan.h +++ b/lib/net/rte_vxlan.h @@ -24,6 +24,7 @@ extern "C" { /** VXLAN default port. */ #define RTE_VXLAN_DEFAULT_PORT 4789 #define RTE_VXLAN_GPE_DEFAULT_PORT 4790 +#define RTE_VXLAN_FLAGS_I (1 << 3) /** * VXLAN protocol header. @@ -31,7 +32,14 @@ extern "C" { * Reserved fields (24 bits and 8 bits) */ struct rte_vxlan_hdr { - rte_be32_t vx_flags; /**< flag (8) + Reserved (24). */ + RTE_STD_C11 + union { + struct { + uint8_t vx_flag_bits; + uint8_t reserved[3]; + }; + rte_be32_t vx_flags; /**< flag (8) + Reserved (24). */ + }; rte_be32_t vx_vni; /**< VNI (24) + Reserved (8). */ } __rte_packed; From patchwork Fri Jan 21 10:31:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ronan Randles X-Patchwork-Id: 106176 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 3C88AA034E; Fri, 21 Jan 2022 11:33:03 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A21A54279E; Fri, 21 Jan 2022 11:31:50 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id 233E642780 for ; Fri, 21 Jan 2022 11:31:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642761108; x=1674297108; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2wiI4pWI4PvoTw8Q2rDPFJLJwm7iFiWlvhUD830pNUg=; b=QjhyLEospPgb2dT5Ear1ayXBXU+ai4c48PKcgg2IzwSR1ypg6LASyELQ K19q3+npiAJ/vwThad69n5Heme5Tq5V/qaRL1DyOKsDbWg6bHuVfftbXW 3hQKqXdf6B386gZ75Yb5pbbdmuTLF6RLsqb13jX6DH9zTSqxfGlgFJEFS nzMpETiAIWZWTQZc/DrgD418L2OjuOSNGXZdCNJpdQAKFpFo4Tw2K3VJo dq8edCSgNtP4r4xMtSliXCnUZGdPlPdy1gP+kvLKozhhpAPx2NJRFEBoP zFDwk9nCKF3DUhK5j6PAEwtwu7PH+PVYFbKAGc01DGMa2NJ2r5Kf8R4Ma g==; X-IronPort-AV: E=McAfee;i="6200,9189,10233"; a="270045161" X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="270045161" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2022 02:31:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,304,1635231600"; d="scan'208";a="533222808" Received: from silpixa00401120.ir.intel.com ([10.55.128.255]) by orsmga008.jf.intel.com with ESMTP; 21 Jan 2022 02:31:46 -0800 From: Ronan Randles To: dev@dpdk.org Cc: Ronan Randles Subject: [PATCH v2 15/15] gen: add VXLAN support Date: Fri, 21 Jan 2022 10:31:22 +0000 Message-Id: <20220121103122.2926856-16-ronan.randles@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220121103122.2926856-1-ronan.randles@intel.com> References: <20211214141242.3383831-1-ronan.randles@intel.com> <20220121103122.2926856-1-ronan.randles@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit adds VXLAN parsing and logging functionality. Unit test with additional test case to test_gen_packet_parse_string. Signed-off-by: Ronan Randles --- app/test/test_gen.c | 1 + lib/gen/rte_gen.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/app/test/test_gen.c b/app/test/test_gen.c index a0b00d6a6e..f05851831a 100644 --- a/app/test/test_gen.c +++ b/app/test/test_gen.c @@ -138,6 +138,7 @@ test_gen_packet_parse_string(void) { .str = "Ether()/IP(src=1.2.3.fail,dst=5.6.7.8)", .expected_to_fail = 1}, { .str = "Ether()/IP()/UDP()"}, + { .str = "Ether()/IP()/UDP()/VXLAN()"}, }; uint32_t i; diff --git a/lib/gen/rte_gen.c b/lib/gen/rte_gen.c index 3a67ce8b6c..431ffc5b2a 100644 --- a/lib/gen/rte_gen.c +++ b/lib/gen/rte_gen.c @@ -12,6 +12,7 @@ #include #include #include +#include RTE_LOG_REGISTER(gen_logtype, lib.gen, NOTICE); @@ -140,6 +141,7 @@ enum GEN_PROTO { GEN_PROTO_ETHER, GEN_PROTO_IPV4, GEN_PROTO_UDP, + GEN_PROTO_VXLAN, /* Must be last. */ GEN_PROTO_COUNT, @@ -472,6 +474,10 @@ gen_parse_udp(struct gen_parser *parser, char *protocol_str) int err = gen_parser_parse_next(parser, &inner); switch (inner) { + case GEN_PROTO_VXLAN: + udp->src_port = rte_cpu_to_be_16(RTE_VXLAN_DEFAULT_PORT); + udp->dst_port = rte_cpu_to_be_16(RTE_VXLAN_DEFAULT_PORT); + break; default: /* default to DNS like other packet generation tools */ udp->src_port = rte_cpu_to_be_16(53); @@ -490,6 +496,44 @@ gen_parse_udp(struct gen_parser *parser, char *protocol_str) return err; } +static int32_t +gen_parse_vxlan(struct gen_parser *parser, char *protocol_str) +{ + RTE_SET_USED(protocol_str); + struct rte_vxlan_hdr *vxlan = gen_parser_get_data_ptr(parser); + memset(vxlan, 0, sizeof(*vxlan)); + + uint32_t input_vni = 1000; + vxlan->vx_vni = rte_cpu_to_be_32(input_vni << 8); + + /* Move up write pointer in packet. */ + parser->buf_write_offset += sizeof(*vxlan); + + enum GEN_PROTO inner; + int err = gen_parser_parse_next(parser, &inner); + + vxlan->vx_flag_bits = RTE_VXLAN_FLAGS_I; + + switch (inner) { + default: + /* Not supporting VXLAN-GPE and next proto today. */ + break; + } + + return err; +} + +static void +gen_log_vxlan(void *data, const char *indent) +{ + struct rte_vxlan_hdr *vxlan = data; + + GEN_LOG_PROTOCOL(DEBUG, + "###[ VXLAN ]###\n%svx_flags= %u\n%svx_vni= %u\n", + indent, rte_be_to_cpu_32(vxlan->vx_flags), + indent, rte_be_to_cpu_32(vxlan->vx_vni)); +} + /* (Name, Function-pointer) pairs for supported parse types */ typedef int32_t (*gen_parse_func)(struct gen_parser *parser, char *protocol_str); @@ -520,6 +564,12 @@ static struct gen_parse_func_t gen_protocols[] = { .proto = GEN_PROTO_UDP, .parse_func = gen_parse_udp, .log_func = gen_log_udp, + }, + { + .name = "VXLAN(", + .proto = GEN_PROTO_VXLAN, + .parse_func = gen_parse_vxlan, + .log_func = gen_log_vxlan, } };