From patchwork Tue Sep 26 11:37:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ori Kam X-Patchwork-Id: 131963 X-Patchwork-Delegate: ferruh.yigit@amd.com 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 CF56A42642; Tue, 26 Sep 2023 13:39:05 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5CF49402CA; Tue, 26 Sep 2023 13:39:05 +0200 (CEST) Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2062.outbound.protection.outlook.com [40.107.223.62]) by mails.dpdk.org (Postfix) with ESMTP id 3E9FD402AA for ; Tue, 26 Sep 2023 13:39:04 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YZDpaHyedCGcSbq4xd4ce4fmvZuztNLnG0BIPXrhWuo/+VBqwNDlw11FDtMRM/92w4K5mz6PQChzZGO+c9/aiDBe7RVknIfSLZjxchtFQQHTygW2Al0jO76JgGAFL/SRBsZz+O1i1IEP/tO0iCP91GiBb+k/+2dzhjj327dD6/XQPwWGpLxZvCjwA8RoR7IQVmJNGiKmekAOLaXfR3FSNkm0IUV6nUCbogHZ8kVTPcVywFOfym1Yd7T4rWfzviAjhWfXTHn17vkFzJ7NqSph84NwcvLX45bOJ2S0GWx+2U7TCu6f8SlVo7HEOGq9Um3SoOTiJCWrOvcjWqvP5M93IA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pyQgQApHZ+g7rE0Lq1OQgpwEo5mrXPaUZ5EhU918jpw=; b=BxPc4TZ5SnLWsXtBj6kqw3yyq2KtuDEUNJstoJMKOMpGHZ03JrtIu+py0sKUXTCANTf8/TQiZmpN9Gsb46eHCHXYNzK0qsrLiEMe23pWo4pST9bfGhDjAofGT8EIknHgmPsTwmeb+raL0nute5HgK/iCJMBgF5tDJ1UBIuQ6VorDX6xEm7LYdq3p5kDorhWgDufipq2Z2tXCmzv57mNoa1WzvffJ2lGXuUuGGcSXMW5au4fGhfSvXvC9WhprQTbRUr1nKlUXj5S5NWsOl5hqmRqgADbWhArq3U+wADYcuRbmsb2u1xMVqLw7OqGHzJ0YkdHW0ZeCf7Kn4yWAVlfXAQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.117.160) smtp.rcpttodomain=intel.com smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pyQgQApHZ+g7rE0Lq1OQgpwEo5mrXPaUZ5EhU918jpw=; b=LwYTxxhTOrWmpEfQPn8q/9blABbdPc0lfuG4adtV6r7iyu33G1x1qZjbQThD192MNjSlGvJG9+9NCI/FdSA9qSOpS7qhTXHkl2quNL28J/0bMORkfFvZ3pufQ1wxwE+Kejg0jm2rNzKTavveeivwTDPSNDM3NyOcY4k+8GW8tJ0D2nugugsh2UjXDrcmnN+WeGancuQGNOSI53WPDeYWzeIHku2iW3nTY9hTAnjPcPrOpFbdo5s1YPWq0/kh0WrMtzoWY1bhSll5IIts6DXTmPt7jL5eXj8nfEw59pDByyeNlAeBj78A2ZIhC7dWu/v7yz8IICUXIlgvTdx0n8o/SQ== Received: from MN2PR03CA0023.namprd03.prod.outlook.com (2603:10b6:208:23a::28) by SA1PR12MB8946.namprd12.prod.outlook.com (2603:10b6:806:375::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6813.28; Tue, 26 Sep 2023 11:39:01 +0000 Received: from BL02EPF0001A106.namprd05.prod.outlook.com (2603:10b6:208:23a:cafe::94) by MN2PR03CA0023.outlook.office365.com (2603:10b6:208:23a::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6792.35 via Frontend Transport; Tue, 26 Sep 2023 11:39:01 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.117.160) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.117.160 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.117.160; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.117.160) by BL02EPF0001A106.mail.protection.outlook.com (10.167.241.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6838.14 via Frontend Transport; Tue, 26 Sep 2023 11:39:01 +0000 Received: from rnnvmail202.nvidia.com (10.129.68.7) by mail.nvidia.com (10.129.200.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Tue, 26 Sep 2023 04:38:45 -0700 Received: from nvidia.com (10.126.231.35) by rnnvmail202.nvidia.com (10.129.68.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Tue, 26 Sep 2023 04:38:42 -0700 From: Ori Kam To: , Aman Singh , Yuying Zhang , Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko CC: , , Subject: [PATCH] ethdev: add calculate hash function Date: Tue, 26 Sep 2023 14:37:52 +0300 Message-ID: <20230926113753.28765-1-orika@nvidia.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Originating-IP: [10.126.231.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail202.nvidia.com (10.129.68.7) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF0001A106:EE_|SA1PR12MB8946:EE_ X-MS-Office365-Filtering-Correlation-Id: 7027c355-19e6-4191-8c8f-08dbbe852de9 X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: VVVzsx6QHc31+5xa77CS2s+4jYOIZzl6xqQQLUm2KwGas2N7HogidUl2n+QipRfJKdlDdccOuctbPDdlYmnWIKxPBaLkbYU5BrhrBK+fchqPKcICRMmap6FaGSERR+aArYue84JqIaIspi/2iQgnJazDTC7tDpxtTlAxPrgY4uqgatyp/DI0W+mwQK0HvKWGELUFdeBshEhsaGQcECZ99BSv1/dclssXLfLTMjUyJsX38qxbqDbaYCWafYnooWsHdJzFUWObiJWLxYNSqYVqgwFMjmp5AlD5Ax5aj57QhtmCBsQlN9X+8si0asoSR5MnRciA+Ua4+ryEL1P1RXzZuDFiRG+jaP5PUl6QuYKA8Fa3YhoPmRdqZA5tKClrNwrztPNBe+cMGPyuhkL1lPPI2vtU6HCa4bvmAeGr97LqdJluZSs4O43UhNPboPIPavGH4mC5XeAAUGQgeduGeUqUfjG4LNFCs+yKjFbdOTKIZ3TiAQbIs9kyfn3sU8fvRMEJEAKhPXKPB10ktKiN27fXpTvs9DIgOLV/hanDhQ6VsmYEjPB1R8MnCdliFMXRGb39phVOhn1ATwIILo3VGwTb6wBfI1DWiWg4cggZX0SBTUR0xyd2lhAjtLyXul/L5b13FSCF+lcSC646vPr2xfCQCB56oVxBs9g/4USoHoaCVuExsKeSNEdbUR+tB0i+6lHTXmEUIpB8PUZtIFu+BmAKXry4v3Gq6vUO6FYzUjnn3Ld7wGJxPSbzs9qBYkVXn2B6xrqT1GT3D+hNY+e48GO46Q== X-Forefront-Antispam-Report: CIP:216.228.117.160; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge1.nvidia.com; CAT:NONE; SFS:(13230031)(4636009)(39860400002)(136003)(346002)(396003)(376002)(230922051799003)(82310400011)(186009)(1800799009)(451199024)(36840700001)(46966006)(40470700004)(36756003)(86362001)(30864003)(40480700001)(55016003)(5660300002)(7696005)(2906002)(2616005)(70586007)(70206006)(110136005)(41300700001)(478600001)(54906003)(316002)(6666004)(966005)(47076005)(40460700003)(426003)(83380400001)(4326008)(356005)(36860700001)(7636003)(8676002)(8936002)(82740400003)(16526019)(107886003)(336012)(1076003)(6286002)(26005); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Sep 2023 11:39:01.1234 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7027c355-19e6-4191-8c8f-08dbbe852de9 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.160]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF0001A106.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA1PR12MB8946 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 rte_flow supports insert by index table[1]. Using the above table, the application can create rules that are based on hash. For example application can create the following logic in order to create load balancing: 1. Create insert by index table with 2 rules, that hashes based on dmac 2. Insert to index 0 a rule that sends the traffic to port A. 3. Insert to index 1 a rule that sends the traffic to port B. Let's also assume that before this table, there is a 5 tuple match table that jumps to the above table. So each packet that matches one of the 5 tuple rules is RSSed to port A or B, based on dmac hash. The issue arises when there is a miss on the 5 tuple table, which resulted due to the packet being the first packet of this flow, or fragmented packet or any other reason. In this case, the application must calculate what would be the hash calculated by the HW so it can send the packet to the correct port. This new API allows applications to calculate the hash value of a given packet for a given table. [1] - http://patches.dpdk.org/project/dpdk/patch/20230208030624.78465-2-akozyrev@nvidia.com/ Signed-off-by: Ori Kam Acked-by: Dariusz Sosnowski --- app/test-pmd/cmdline_flow.c | 86 +++++++++++++++++++++++++++++++++++- app/test-pmd/config.c | 54 ++++++++++++++++++++++ app/test-pmd/testpmd.h | 2 + lib/ethdev/rte_flow.c | 21 +++++++++ lib/ethdev/rte_flow.h | 32 ++++++++++++++ lib/ethdev/rte_flow_driver.h | 5 +++ lib/ethdev/version.map | 1 + 7 files changed, 200 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 94827bcc4a..e1e4bb49fa 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -101,6 +101,7 @@ enum index { QUEUE, PUSH, PULL, + HASH, /* Flex arguments */ FLEX_ITEM_INIT, @@ -206,6 +207,11 @@ enum index { TABLE_PATTERN_TEMPLATE, TABLE_ACTIONS_TEMPLATE, + /* Hash calculation arguments. */ + HASH_CALC_TABLE, + HASH_CALC_PATTERN_INDEX, + HASH_CALC_PATTERN, + /* Tunnel arguments. */ TUNNEL_CREATE, TUNNEL_CREATE_TYPE, @@ -2678,6 +2684,9 @@ static int parse_push(struct context *, const struct token *, static int parse_pull(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_hash(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -3035,7 +3044,8 @@ static const struct token token_list[] = { FLEX, QUEUE, PUSH, - PULL)), + PULL, + HASH)), .call = parse_init, }, /* Top-level command. */ @@ -3680,6 +3690,33 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, queue)), }, /* Top-level command. */ + [HASH] = { + .name = "hash", + .help = "calculate hash for a given pattern in a given template table", + .next = NEXT(NEXT_ENTRY(HASH_CALC_TABLE), NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_hash, + }, + /* Sub-level commands. */ + [HASH_CALC_TABLE] = { + .name = "template_table", + .help = "specify table id", + .next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX), + NEXT_ENTRY(COMMON_TABLE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.vc.table_id)), + .call = parse_hash, + }, + [HASH_CALC_PATTERN_INDEX] = { + .name = "pattern_template", + .help = "specify pattern template id", + .next = NEXT(NEXT_ENTRY(ITEM_PATTERN), + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.vc.pat_templ_id)), + .call = parse_hash, + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -10449,6 +10486,48 @@ parse_pull(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for hash calculation commands. */ +static int +parse_hash(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != HASH) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + return len; + } + switch (ctx->curr) { + case HASH_CALC_TABLE: + case HASH_CALC_PATTERN_INDEX: + return len; + case ITEM_PATTERN: + out->args.vc.pattern = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + ctx->object = out->args.vc.pattern; + ctx->objmask = NULL; + return len; + default: + return -1; + } +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -12351,6 +12430,11 @@ cmd_flow_parsed(const struct buffer *in) case PULL: port_queue_flow_pull(in->port, in->queue); break; + case HASH: + port_flow_hash_calc(in->port, in->args.vc.table_id, + in->args.vc.pat_templ_id, + in->args.vc.pattern); + break; case QUEUE_AGED: port_queue_flow_aged(in->port, in->queue, in->args.aged.destroy); diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 11f3a22048..c244f1a071 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -3301,6 +3302,59 @@ port_queue_flow_push(portid_t port_id, queueid_t queue_id) return ret; } +/** Calculate the hash result for a given pattern in a given table. */ +int +port_flow_hash_calc(portid_t port_id, uint32_t table_id, + uint8_t pattern_template_index, const struct rte_flow_item pattern[]) +{ + uint32_t hash; + bool found; + struct port_table *pt; + struct rte_port *port; + struct rte_flow_error error; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + + found = false; + pt = port->table_list; + while (pt) { + if (table_id == pt->id) { + found = true; + break; + } + pt = pt->next; + } + if (!found) { + printf("Table #%u is invalid\n", table_id); + return -EINVAL; + } + + memset(&error, 0x55, sizeof(error)); + ret = rte_flow_calc_table_hash(port_id, pt->table, pattern, + pattern_template_index, &hash, &error); + if (ret < 0) { + printf("Failed to calculate hash "); + switch (abs(ret)) { + case ENODEV: + printf("no such device\n"); + break; + case ENOTSUP: + printf("device doesn't support this operation\n"); + break; + default: + printf("\n"); + break; + } + return ret; + } + printf("Hash results 0x%x\n", hash); + return 0; +} + /** Pull queue operation results from the queue. */ static int port_queue_aged_flow_destroy(portid_t port_id, queueid_t queue_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index f1df6a8faf..4637a47c06 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1009,6 +1009,8 @@ port_queue_action_handle_query_update(portid_t port_id, const struct rte_flow_action *action); int port_queue_flow_push(portid_t port_id, queueid_t queue_id); int port_queue_flow_pull(portid_t port_id, queueid_t queue_id); +int port_flow_hash_calc(portid_t port_id, uint32_t table_id, + uint8_t pattern_template_index, const struct rte_flow_item pattern[]); void port_queue_flow_aged(portid_t port_id, uint32_t queue_id, uint8_t destroy); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 271d854f78..5f7dcdfdad 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -2431,3 +2431,24 @@ rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_ ret); return ret; } + +int +rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table *table, + const struct rte_flow_item pattern[], uint8_t pattern_template_index, + uint32_t *hash, struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev; + const struct rte_flow_ops *ops; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + ops = rte_flow_ops_get(port_id, error); + if (!ops || !ops->flow_calc_table_hash) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "action_list async query_update not supported"); + dev = &rte_eth_devices[port_id]; + ret = ops->flow_calc_table_hash(dev, table, pattern, pattern_template_index, + hash, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 23addb4382..b8c28394a1 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -6624,6 +6624,38 @@ rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_ void *user_data, struct rte_flow_error *error); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Calculate the hash for a given pattern in a given table as + * calculated by the HW. + * + * @param port_id + * Port identifier of Ethernet device. + * @param table + * The table the SW wishes to simulate. + * @param pattern + * The values to be used in the hash calculation. + * @param pattern_template_index + * The pattern index in the table to be used for the calculation. + * @param hash + * Used to return the calculated hash. + * @param error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * - (0) if success. + * - (-ENODEV) if *port_id* invalid. + * - (-ENOTSUP) if underlying device does not support this functionality. + */ +__rte_experimental +int +rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table *table, + const struct rte_flow_item pattern[], uint8_t pattern_template_index, + uint32_t *hash, struct rte_flow_error *error); + #ifdef __cplusplus } #endif diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index f9fb01b8a2..aa8635b1a8 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -358,6 +358,11 @@ struct rte_flow_ops { const void **update, void **query, enum rte_flow_query_update_mode mode, void *user_data, struct rte_flow_error *error); + /** @see rte_flow_calc_table_hash() */ + int (*flow_calc_table_hash) + (struct rte_eth_dev *dev, const struct rte_flow_template_table *table, + const struct rte_flow_item pattern[], uint8_t pattern_template_index, + uint32_t *hash, struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index b965d6aa52..1496d8caa6 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -312,6 +312,7 @@ EXPERIMENTAL { rte_flow_async_action_list_handle_query_update; rte_flow_async_actions_update; rte_flow_restore_info_dynflag; + rte_flow_calc_table_hash; }; INTERNAL {