From patchwork Tue Jan 23 00:16:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Washington X-Patchwork-Id: 136051 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 5B79A4399F; Tue, 23 Jan 2024 01:17:39 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3E80C40DDA; Tue, 23 Jan 2024 01:17:22 +0100 (CET) Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) by mails.dpdk.org (Postfix) with ESMTP id 7E45E406A2 for ; Tue, 23 Jan 2024 01:17:20 +0100 (CET) Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-dc26605c273so5660423276.0 for ; Mon, 22 Jan 2024 16:17:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705969040; x=1706573840; darn=dpdk.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5aMu/TzmyRWtfXAU0eOO7y6zOxVHB1jkj7quREYJKgw=; b=GJoPhWkBBSn/3rB9jJtW2zbr+QWsyMeiyNtOFguzI4nyWa/gXX4WSg/QTMAspgCwDQ 2JYw/qHLtDZfBKwEhgTBlmFfBqDZcHwDJj3dKGE9UkX2s0lwkUV5L3G9v9W+h1TkBDTy 4TSz5rvUShBVhLi26+pVPm47J6E+rA38B8NQgLlJVMugMv1PFusYKFBLOmgQVEyYQOBw vwXo7WaLONOzbSVfS0Ha7QWvR/p/i11KSDaH+2PK65koAbaX0XTSjbJjNtHZxQgQQHVt D8U6Pp25tUF0GGrGR6zWzZKf0DwuzidbPMsMoxj1gJKdryhhe7HwwrNP1Mf7A10ZYCRH Fcqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705969040; x=1706573840; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5aMu/TzmyRWtfXAU0eOO7y6zOxVHB1jkj7quREYJKgw=; b=LQpSc5O2xdTf7+lK6Mix6adM1XG7TDV8TN4N4Bp1fwowO7Uvp+cHLvX55rIGdxnrbp QncXXb+G+FXfqzVS5YUAUk8TDQ5+SHJbTMwtbQCE8pjul+fN5+G/f9eJ1x3eXvc6G2vj 2Ckh701Xu3X7rNyZsRwqbVnOE97b7tgmIqHPDXqpAXwwJCdNquE/gWZ1TtNbNs1qep7t aWmg6WF8+bWK9y3WC/BZfk47cx6nDfN+yAm5TAhA2nFYDZ/jqnVfuvNX7QG5rC0gT4Y8 tmJ4RgTEgoGUWPKvbArKdgb2ABFDl0CFGM1QXYJSio9a91DPICZZO0jXYUQoCaB/DSdm ILZw== X-Gm-Message-State: AOJu0YxRdb/+ZChAFughdl88/qGBk7v2t+0peNVDhA2MuI/YhQq9uUf/ ez8X4WZlA1UIx3LNLgSiFeQi/wWZeeR93DpIA4teY7Tjbb7QKLj1BrSSUkVJ5aQeWtXtQ9cFow1 u/V7pzR1u6w== X-Google-Smtp-Source: AGHT+IFpeGgQbXbAyDMiS0I2E0jSfI35ruV9lVqZpdcpaNcEQgbxRj1qkkNXBL2FL5va3DJ4bnChuD1WpS1hHg== X-Received: from joshwash.sea.corp.google.com ([2620:15c:11c:202:9096:2b97:b7f7:1182]) (user=joshwash job=sendgmr) by 2002:a25:4607:0:b0:dc2:3441:897f with SMTP id t7-20020a254607000000b00dc23441897fmr2340805yba.6.1705969039778; Mon, 22 Jan 2024 16:17:19 -0800 (PST) Date: Mon, 22 Jan 2024 16:16:40 -0800 In-Reply-To: <20240123001645.1507779-1-joshwash@google.com> Mime-Version: 1.0 References: <20240123001645.1507779-1-joshwash@google.com> X-Mailer: git-send-email 2.43.0.429.g432eaa2c6b-goog Message-ID: <20240123001645.1507779-4-joshwash@google.com> Subject: [PATCH 3/7] net/gve: add gve_rss library for handling RSS-related behaviors From: Joshua Washington To: Junfeng Guo , Jeroen de Borst , Rushil Gupta , Joshua Washington Cc: dev@dpdk.org, Ferruh Yigit 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 change includes a number of helper functions to facilitate RSS configuration on the GVE DPDK driver. These methods are declared in gve_rss.h. --- drivers/net/gve/base/gve_adminq.h | 10 +- drivers/net/gve/gve_ethdev.c | 2 +- drivers/net/gve/gve_ethdev.h | 4 +- drivers/net/gve/gve_rss.c | 206 ++++++++++++++++++++++++++++++ drivers/net/gve/gve_rss.h | 107 ++++++++++++++++ drivers/net/gve/meson.build | 1 + 6 files changed, 319 insertions(+), 11 deletions(-) create mode 100644 drivers/net/gve/gve_rss.c create mode 100644 drivers/net/gve/gve_rss.h diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h index 95f4960561..24abd945cc 100644 --- a/drivers/net/gve/base/gve_adminq.h +++ b/drivers/net/gve/base/gve_adminq.h @@ -378,15 +378,6 @@ struct gve_adminq_get_ptype_map { __be64 ptype_map_addr; }; -#define GVE_RSS_HASH_IPV4 BIT(0) -#define GVE_RSS_HASH_TCPV4 BIT(1) -#define GVE_RSS_HASH_IPV6 BIT(2) -#define GVE_RSS_HASH_IPV6_EX BIT(3) -#define GVE_RSS_HASH_TCPV6 BIT(4) -#define GVE_RSS_HASH_TCPV6_EX BIT(5) -#define GVE_RSS_HASH_UDPV4 BIT(6) -#define GVE_RSS_HASH_UDPV6 BIT(7) -#define GVE_RSS_HASH_UDPV6_EX BIT(8) /* RSS configuration command */ struct gve_adminq_configure_rss { @@ -428,6 +419,7 @@ union gve_adminq_command { GVE_CHECK_UNION_LEN(64, gve_adminq_command); struct gve_priv; +struct gve_rss_config; struct gve_queue_page_list; int gve_adminq_alloc(struct gve_priv *priv); void gve_adminq_free(struct gve_priv *priv); diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c index 6acdb4e13b..936ca22cb9 100644 --- a/drivers/net/gve/gve_ethdev.c +++ b/drivers/net/gve/gve_ethdev.c @@ -442,7 +442,7 @@ gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .nb_align = 1, }; - dev_info->flow_type_rss_offloads = GVE_RSS_OFFLOAD_ALL; + dev_info->flow_type_rss_offloads = GVE_RTE_RSS_OFFLOAD_ALL; return 0; } diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h index aa8291f235..b5118e737a 100644 --- a/drivers/net/gve/gve_ethdev.h +++ b/drivers/net/gve/gve_ethdev.h @@ -33,7 +33,7 @@ RTE_MBUF_F_TX_L4_MASK | \ RTE_MBUF_F_TX_TCP_SEG) -#define GVE_RSS_OFFLOAD_ALL ( \ +#define GVE_RTE_RSS_OFFLOAD_ALL ( \ RTE_ETH_RSS_IPV4 | \ RTE_ETH_RSS_NONFRAG_IPV4_TCP | \ RTE_ETH_RSS_IPV6 | \ @@ -290,6 +290,8 @@ struct gve_priv { const struct rte_memzone *stats_report_mem; uint16_t stats_start_idx; /* start index of array of stats written by NIC */ uint16_t stats_end_idx; /* end index of array of stats written by NIC */ + + struct gve_rss_config rss_config; }; static inline bool diff --git a/drivers/net/gve/gve_rss.c b/drivers/net/gve/gve_rss.c new file mode 100644 index 0000000000..b1cd0e16f2 --- /dev/null +++ b/drivers/net/gve/gve_rss.c @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Google LLC + */ + +#include "gve_rss.h" + +int +gve_generate_rss_reta(struct rte_eth_dev *dev, struct gve_rss_config* config) +{ + int i; + if (!config || !config->indir) { + return -EINVAL; + } + + for (i = 0; i < config->indir_size; i++) + config->indir[i] = i % dev->data->nb_rx_queues; + + return 0; +} + + +int +gve_init_rss_config(struct gve_rss_config *gve_rss_conf, + uint16_t key_size, uint16_t indir_size) +{ + int err; + + gve_rss_conf->alg = GVE_RSS_HASH_TOEPLITZ; + + gve_rss_conf->key_size = key_size; + gve_rss_conf->key = rte_zmalloc("rss key", + key_size * sizeof(*gve_rss_conf->key), + RTE_CACHE_LINE_SIZE); + if (!gve_rss_conf->key) { + return -ENOMEM; + } + + gve_rss_conf->indir_size = indir_size; + gve_rss_conf->indir = rte_zmalloc("rss reta", + indir_size * sizeof(*gve_rss_conf->indir), + RTE_CACHE_LINE_SIZE); + if (!gve_rss_conf->indir) { + err = -ENOMEM; + goto err_with_key; + } + + return 0; +err_with_key: + rte_free(gve_rss_conf->key); + return err; +} + +int +gve_init_rss_config_from_priv(struct gve_priv *priv, + struct gve_rss_config *gve_rss_conf) +{ + int err = gve_init_rss_config(gve_rss_conf, priv->rss_config.key_size, + priv->rss_config.indir_size); + if (err) + return err; + + gve_rss_conf->hash_types = priv->rss_config.hash_types; + gve_rss_conf->alg = priv->rss_config.alg; + memcpy(gve_rss_conf->key, priv->rss_config.key, + gve_rss_conf->key_size * sizeof(*gve_rss_conf->key)); + memcpy(gve_rss_conf->indir, priv->rss_config.indir, + gve_rss_conf->indir_size * sizeof(*gve_rss_conf->indir)); + + return 0; +} + +void +gve_free_rss_config(struct gve_rss_config *gve_rss_conf) +{ + rte_free(gve_rss_conf->indir); + gve_rss_conf->indir = NULL; + rte_free(gve_rss_conf->key); + gve_rss_conf->key = NULL; +} + +int +gve_update_priv_rss_config(struct gve_priv *priv, struct gve_rss_config *config) +{ + struct gve_rss_config *priv_config = &priv->rss_config; + int key_bytes, indir_bytes; + + if (!config) + return -EINVAL; + if (config->key_size == 0 || !config->key) + return -EINVAL; + if (config->indir_size == 0 || !config->indir) + return -EINVAL; + + priv_config->hash_types = config->hash_types; + priv_config->alg = config->alg; + + priv_config->key_size = config->key_size; + key_bytes = priv_config->key_size * sizeof(*priv_config->key); + if (!priv_config->key) + priv_config->key = rte_zmalloc("priv rss key", key_bytes, + RTE_CACHE_LINE_SIZE); + else + priv_config->key = rte_realloc(priv_config->key, key_bytes, + RTE_CACHE_LINE_SIZE); + if (!priv_config->key) + return -ENOMEM; + + priv_config->indir_size = config->indir_size; + indir_bytes = priv_config->indir_size * sizeof(*priv_config->indir); + if (!priv_config->indir) + priv_config->indir = rte_zmalloc("priv rss reta", indir_bytes, + RTE_CACHE_LINE_SIZE); + else + priv_config->indir = rte_realloc(priv_config->indir, + indir_bytes, RTE_CACHE_LINE_SIZE); + + if (!priv_config->indir) + return -ENOMEM; + + memcpy(priv_config->indir, config->indir, + config->indir_size * sizeof(*priv_config->indir)); + memcpy(priv_config->key, config->key, + config->key_size * sizeof(*priv_config->key)); + + return 0; +} + +int +gve_update_rss_key(struct gve_priv *priv, struct gve_rss_config *gve_rss_conf, + struct rte_eth_rss_conf *rss_conf) +{ + if (rss_conf->rss_key_len && rss_conf->rss_key) { + gve_rss_conf->key_size = rss_conf->rss_key_len; + memcpy(gve_rss_conf->key, rss_conf->rss_key, + gve_rss_conf->key_size * sizeof(*gve_rss_conf->key)); + } else if (priv->rss_config.key_size && priv->rss_config.key) { + gve_rss_conf->key_size = priv->rss_config.key_size; + memcpy(gve_rss_conf->key, priv->rss_config.key, + gve_rss_conf->key_size * sizeof(*gve_rss_conf->key)); + } else { + PMD_DRV_LOG(ERR, "RSS key must be set as part of initial RSS " + "configuration."); + return -EINVAL; + } + return 0; +} + +int +gve_update_rss_hash_types(struct gve_priv *priv, + struct gve_rss_config *gve_rss_conf, struct rte_eth_rss_conf *rss_conf) +{ + // Initialize to 0 before modifying. + gve_rss_conf->hash_types = 0; + if (rss_conf->rss_hf) + rte_to_gve_rss_hf(rss_conf->rss_hf, gve_rss_conf); + else if (priv->rss_config.key_size && priv->rss_config.key) + gve_rss_conf->hash_types = priv->rss_config.hash_types; + else + gve_rss_conf->hash_types = GVE_RSS_OFFLOAD_DEFAULT; + return 0; +} + +void +rte_to_gve_rss_hf(uint64_t rte_rss_hf, struct gve_rss_config *gve_rss_conf) { + if (rte_rss_hf & RTE_ETH_RSS_IPV4) + gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV4; + if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) + gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV4; + if (rte_rss_hf & RTE_ETH_RSS_IPV6) + gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV6; + if (rte_rss_hf & RTE_ETH_RSS_IPV6_EX) + gve_rss_conf->hash_types |= GVE_RSS_HASH_IPV6_EX; + if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) + gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV6; + if (rte_rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) + gve_rss_conf->hash_types |= GVE_RSS_HASH_TCPV6_EX; + if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) + gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV4; + if (rte_rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) + gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV6; + if (rte_rss_hf & RTE_ETH_RSS_IPV6_UDP_EX) + gve_rss_conf->hash_types |= GVE_RSS_HASH_UDPV6_EX; +} + +void +gve_to_rte_rss_hf(uint16_t gve_rss_types, struct rte_eth_rss_conf *rss_conf) { + if (gve_rss_types & GVE_RSS_HASH_IPV4) + rss_conf->rss_hf |= RTE_ETH_RSS_IPV4; + if (gve_rss_types & GVE_RSS_HASH_TCPV4) + rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP; + if (gve_rss_types & GVE_RSS_HASH_IPV6) + rss_conf->rss_hf |= RTE_ETH_RSS_IPV6; + if (gve_rss_types & GVE_RSS_HASH_IPV6_EX) + rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_EX; + if (gve_rss_types & GVE_RSS_HASH_TCPV6) + rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP; + if (gve_rss_types & GVE_RSS_HASH_TCPV6_EX) + rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_TCP_EX; + if (gve_rss_types & GVE_RSS_HASH_UDPV4) + rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP; + if (gve_rss_types & GVE_RSS_HASH_UDPV6) + rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP; + if (gve_rss_types & GVE_RSS_HASH_UDPV6_EX) + rss_conf->rss_hf |= RTE_ETH_RSS_IPV6_UDP_EX; +} + diff --git a/drivers/net/gve/gve_rss.h b/drivers/net/gve/gve_rss.h new file mode 100644 index 0000000000..bea16d8508 --- /dev/null +++ b/drivers/net/gve/gve_rss.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Google LLC + */ + +#include "gve_adminq.h" +#include "gve_ethdev.h" + +#define GVE_RSS_HASH_IPV4 BIT(0) +#define GVE_RSS_HASH_TCPV4 BIT(1) +#define GVE_RSS_HASH_IPV6 BIT(2) +#define GVE_RSS_HASH_IPV6_EX BIT(3) +#define GVE_RSS_HASH_TCPV6 BIT(4) +#define GVE_RSS_HASH_TCPV6_EX BIT(5) +#define GVE_RSS_HASH_UDPV4 BIT(6) +#define GVE_RSS_HASH_UDPV6 BIT(7) +#define GVE_RSS_HASH_UDPV6_EX BIT(8) + +#define GVE_RSS_OFFLOAD_DEFAULT ( \ + GVE_RSS_HASH_IPV4 | \ + GVE_RSS_HASH_TCPV4 | \ + GVE_RSS_HASH_IPV6 | \ + GVE_RSS_HASH_IPV6_EX | \ + GVE_RSS_HASH_TCPV6 | \ + GVE_RSS_HASH_TCPV6_EX | \ + GVE_RSS_HASH_UDPV4 | \ + GVE_RSS_HASH_UDPV6 | \ + GVE_RSS_HASH_UDPV6_EX) + +/** + * Generates default RSS redirection table based on the number of queues the + * device is configured with. This assigns hash values to queues in a + * round-robin manner. + */ +int +gve_generate_rss_reta(struct rte_eth_dev *dev, struct gve_rss_config* config); + +/** + * Initializes `gve_rss_conf`, setting the fields to default values and + * allocating memory for the RSS key and redirection table. + */ +int +gve_init_rss_config(struct gve_rss_config *gve_rss_conf, + uint16_t key_size, uint16_t indir_size); + +/** + * Initializes `gve_rss_conf` based on the RSS configuration stored in `priv`. + */ +int +gve_init_rss_config_from_priv(struct gve_priv *priv, + struct gve_rss_config *gve_rss_conf); + +/** + * Frees RSS key and redriection table pointers stored in `gve_rss_conf`. + */ +void +gve_free_rss_config(struct gve_rss_config *gve_rss_conf); + +/** + * Updates the rss_config stored in `priv` with the contents of `config`. + */ +int +gve_update_priv_rss_config(struct gve_priv *priv, + struct gve_rss_config *config); + +/** + * Updates the RSS key stored in `gve_rss_conf`. It is prioritized as follows: + * 1) retrieve from `rss_conf`, if non-null + * 2) retrieve from `priv`, if non-null + * If keys from both sources are unset, return -EINVAL. + */ +int +gve_update_rss_key(struct gve_priv *priv, struct gve_rss_config *gve_rss_conf, + struct rte_eth_rss_conf *rss_conf); + +/** + * Updates the RSS hash types stored in `gve_rss_conf`. It is prioritized as + * follows: + * 1) retreive from `rss_conf`, if set + * 2) retrieve from priv, if RSS has been configured + * 3) set default RSS offload + */ +int +gve_update_rss_hash_types(struct gve_priv *priv, + struct gve_rss_config *gve_rss_conf, struct rte_eth_rss_conf *rss_conf); + +/** + * Ensures that only supported RSS hash fields are set in `rte_rss_hf`. + */ +static inline int +gve_validate_rss_hf(uint64_t rte_rss_hf) { + return rte_rss_hf &~ GVE_RTE_RSS_OFFLOAD_ALL; +} + +/** + * Converts RSS hash types from RTE values to GVE values, storing them in + * `gve_rss_conf`. + */ +void +rte_to_gve_rss_hf(uint64_t rte_rss_hf, struct gve_rss_config *gve_rss_conf); + +/** + * Converts RSS hash types from GVE values to RTE values, storing them in + * `rss_conf`. + */ +void +gve_to_rte_rss_hf(uint16_t gve_rss_types, struct rte_eth_rss_conf *rss_conf); + diff --git a/drivers/net/gve/meson.build b/drivers/net/gve/meson.build index 61d195009c..6da13a8406 100644 --- a/drivers/net/gve/meson.build +++ b/drivers/net/gve/meson.build @@ -15,5 +15,6 @@ sources = files( 'gve_tx_dqo.c', 'gve_ethdev.c', 'gve_version.c', + 'gve_rss.c', ) includes += include_directories('base')