From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id CA904A3160 for ; Sat, 12 Oct 2019 02:28:32 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 531E41EB67; Sat, 12 Oct 2019 02:27:33 +0200 (CEST) Received: from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it [93.145.196.230]) by dpdk.org (Postfix) with ESMTP id 8E4C51EB58 for ; Sat, 12 Oct 2019 02:27:32 +0200 (CEST) Received: from [192.168.2.134] (localhost6.localdomain6 [IPv6:::1]) by devele.ntop.org (Postfix) with ESMTP id 6A91D6C003C for ; Sat, 12 Oct 2019 02:27:32 +0200 (CEST) From: Alfredo Cardigliano To: dev@dpdk.org Date: Sat, 12 Oct 2019 02:27:32 +0200 Message-ID: <157084005241.11524.11028568358016352728.stgit@devele> In-Reply-To: <157083994018.11524.11276616720287263690.stgit@devele> References: <157083994018.11524.11276616720287263690.stgit@devele> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [dpdk-dev] [PATCH 13/17] net/ionic: add RSS support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add code to manipulate the RSS configuration used by the adapter. Signed-off-by: Alfredo Cardigliano Reviewed-by: Shannon Nelson --- doc/guides/nics/features/ionic.ini | 3 + drivers/net/ionic/ionic_ethdev.c | 175 ++++++++++++++++++++++++++++++++++++ drivers/net/ionic/ionic_ethdev.h | 8 ++ drivers/net/ionic/ionic_lif.c | 120 +++++++++++++++++++++++++ drivers/net/ionic/ionic_lif.h | 18 ++++ 5 files changed, 324 insertions(+) diff --git a/doc/guides/nics/features/ionic.ini b/doc/guides/nics/features/ionic.ini index 05bdb2d98..b3f6c3497 100644 --- a/doc/guides/nics/features/ionic.ini +++ b/doc/guides/nics/features/ionic.ini @@ -11,6 +11,9 @@ MTU update = Y Promiscuous mode = Y Allmulticast mode = Y Unicast MAC filter = Y +RSS hash = Y +RSS key update = Y +RSS reta update = Y VLAN filter = Y Flow control = Y Linux UIO = Y diff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c index 46cdee7be..196113089 100644 --- a/drivers/net/ionic/ionic_ethdev.c +++ b/drivers/net/ionic/ionic_ethdev.c @@ -33,6 +33,14 @@ static int ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev, struct rte_eth_fc_conf *fc_conf); static int ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev, struct rte_eth_fc_conf *fc_conf); +static int ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); +static int ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); +static int ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf); +static int ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf); int ionic_logtype_init; int ionic_logtype_driver; @@ -64,6 +72,10 @@ static const struct eth_dev_ops ionic_eth_dev_ops = { .allmulticast_disable = ionic_dev_allmulticast_disable, .flow_ctrl_get = ionic_flow_ctrl_get, .flow_ctrl_set = ionic_flow_ctrl_set, + .reta_update = ionic_dev_rss_reta_update, + .reta_query = ionic_dev_rss_reta_query, + .rss_hash_conf_get = ionic_dev_rss_hash_conf_get, + .rss_hash_update = ionic_dev_rss_hash_update, }; /* @@ -243,6 +255,10 @@ ionic_dev_info_get(struct rte_eth_dev *eth_dev, dev_info->max_rx_pktlen = IONIC_MAX_MTU + RTE_ETHER_HDR_LEN; dev_info->max_mac_addrs = adapter->max_mac_addrs; + dev_info->hash_key_size = IONIC_RSS_HASH_KEY_SIZE; + dev_info->reta_size = ident->lif.eth.rss_ind_tbl_sz; + dev_info->flow_type_rss_offloads = IONIC_ETH_RSS_OFFLOAD_ALL; + dev_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G | @@ -303,6 +319,165 @@ ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev, return 0; } +static int +ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + struct ionic_adapter *adapter = lif->adapter; + struct ionic_identity *ident = &adapter->ident; + uint32_t i, j, index, num; + + ionic_init_print_call(); + + if (!lif->rss_ind_tbl) { + ionic_drv_print(ERR, "RSS RETA not initialized, " + "can't update the table"); + return -EINVAL; + } + + if (reta_size != ident->lif.eth.rss_ind_tbl_sz) { + ionic_drv_print(ERR, "The size of hash lookup table configured " + "(%d) doesn't match the number hardware can supported " + "(%d)", + reta_size, ident->lif.eth.rss_ind_tbl_sz); + return -EINVAL; + } + + num = lif->adapter->ident.lif.eth.rss_ind_tbl_sz / RTE_RETA_GROUP_SIZE; + + for (i = 0; i < num; i++) { + for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) { + if (reta_conf[i].mask & ((uint64_t)1 << j)) { + index = (i * RTE_RETA_GROUP_SIZE) + j; + lif->rss_ind_tbl[index] = reta_conf[i].reta[j]; + } + } + } + + return ionic_lif_rss_config(lif, lif->rss_types, NULL, NULL); +} + +static int +ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + struct ionic_adapter *adapter = lif->adapter; + struct ionic_identity *ident = &adapter->ident; + int i, num; + + ionic_init_print_call(); + + if (reta_size != ident->lif.eth.rss_ind_tbl_sz) { + ionic_drv_print(ERR, "The size of hash lookup table configured " + "(%d) doesn't match the number hardware can supported " + "(%d)", + reta_size, ident->lif.eth.rss_ind_tbl_sz); + return -EINVAL; + } + + if (!lif->rss_ind_tbl) { + ionic_drv_print(ERR, "RSS RETA has not been built yet"); + return -EINVAL; + } + + num = reta_size / RTE_RETA_GROUP_SIZE; + + for (i = 0; i < num; i++) { + memcpy(reta_conf->reta, + &lif->rss_ind_tbl[i * RTE_RETA_GROUP_SIZE], + RTE_RETA_GROUP_SIZE); + reta_conf++; + } + + return 0; +} + +static int +ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + uint64_t rss_hf = 0; + + ionic_init_print_call(); + + if (!lif->rss_ind_tbl) { + ionic_drv_print(NOTICE, "RSS not enabled"); + return 0; + } + + /* Get key value (if not null, rss_key is 40-byte) */ + if (rss_conf->rss_key != NULL && + rss_conf->rss_key_len >= IONIC_RSS_HASH_KEY_SIZE) + memcpy(rss_conf->rss_key, lif->rss_hash_key, + IONIC_RSS_HASH_KEY_SIZE); + + if (lif->rss_types & IONIC_RSS_TYPE_IPV4) + rss_hf |= ETH_RSS_IPV4; + if (lif->rss_types & IONIC_RSS_TYPE_IPV4_TCP) + rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP; + if (lif->rss_types & IONIC_RSS_TYPE_IPV4_UDP) + rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP; + if (lif->rss_types & IONIC_RSS_TYPE_IPV6) + rss_hf |= ETH_RSS_IPV6; + if (lif->rss_types & IONIC_RSS_TYPE_IPV6_TCP) + rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP; + if (lif->rss_types & IONIC_RSS_TYPE_IPV6_UDP) + rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP; + + rss_conf->rss_hf = rss_hf; + + return 0; +} + +static int +ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); + uint32_t rss_types = 0; + uint8_t *key = NULL; + + ionic_init_print_call(); + + if (rss_conf->rss_key) + key = rss_conf->rss_key; + + if ((rss_conf->rss_hf & IONIC_ETH_RSS_OFFLOAD_ALL) == 0) { + /* + * Can't disable rss through hash flags, + * if it is enabled by default during init + */ + if (lif->rss_ind_tbl) + return -EINVAL; + } else { + /* Can't enable rss if disabled by default during init */ + if (!lif->rss_ind_tbl) + return -EINVAL; + + if (rss_conf->rss_hf & ETH_RSS_IPV4) + rss_types |= IONIC_RSS_TYPE_IPV4; + if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) + rss_types |= IONIC_RSS_TYPE_IPV4_TCP; + if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) + rss_types |= IONIC_RSS_TYPE_IPV4_UDP; + if (rss_conf->rss_hf & ETH_RSS_IPV6) + rss_types |= IONIC_RSS_TYPE_IPV6; + if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) + rss_types |= IONIC_RSS_TYPE_IPV6_TCP; + if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) + rss_types |= IONIC_RSS_TYPE_IPV6_UDP; + + ionic_lif_rss_config(lif, rss_types, key, NULL); + } + + return 0; +} + static int ionic_dev_configure(struct rte_eth_dev *eth_dev) { diff --git a/drivers/net/ionic/ionic_ethdev.h b/drivers/net/ionic/ionic_ethdev.h index 9f1c0320d..914e36dfb 100644 --- a/drivers/net/ionic/ionic_ethdev.h +++ b/drivers/net/ionic/ionic_ethdev.h @@ -5,6 +5,14 @@ #ifndef _IONIC_ETHDEV_H_ #define _IONIC_ETHDEV_H_ +#define IONIC_ETH_RSS_OFFLOAD_ALL ( \ + ETH_RSS_IPV4 | \ + ETH_RSS_NONFRAG_IPV4_TCP | \ + ETH_RSS_NONFRAG_IPV4_UDP | \ + ETH_RSS_IPV6 | \ + ETH_RSS_NONFRAG_IPV6_TCP | \ + ETH_RSS_NONFRAG_IPV6_UDP) + #define IONIC_ETH_DEV_TO_LIF(eth_dev) ((struct ionic_lif *) \ eth_dev->data->dev_private) #define IONIC_ETH_DEV_TO_ADAPTER(eth_dev) \ diff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c index 0ab0f9e5e..045994787 100644 --- a/drivers/net/ionic/ionic_lif.c +++ b/drivers/net/ionic/ionic_lif.c @@ -714,6 +714,97 @@ ionic_lif_free(struct ionic_lif *lif) rte_memzone_free(lif->info_z); } +int +ionic_lif_rss_config(struct ionic_lif *lif, + const uint16_t types, const uint8_t *key, const uint32_t *indir) +{ + struct ionic_admin_ctx ctx = { + .pending_work = true, + .cmd.lif_setattr = { + .opcode = IONIC_CMD_LIF_SETATTR, + .attr = IONIC_LIF_ATTR_RSS, + .rss.types = types, + .rss.addr = lif->rss_ind_tbl_pa, + }, + }; + unsigned int i; + + ionic_init_print_call(); + + lif->rss_types = types; + + if (key) + memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); + + if (indir) + for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++) + lif->rss_ind_tbl[i] = indir[i]; + + memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, + IONIC_RSS_HASH_KEY_SIZE); + + return ionic_adminq_post_wait(lif, &ctx); +} + +static int +ionic_lif_rss_setup(struct ionic_lif *lif) +{ + size_t tbl_size = sizeof(*lif->rss_ind_tbl) * + lif->adapter->ident.lif.eth.rss_ind_tbl_sz; + static const uint8_t toeplitz_symmetric_key[] = { + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + }; + uint32_t socket_id = rte_socket_id(); + uint32_t i; + int err; + + ionic_init_print_call(); + + lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev, + "rss_ind_tbl", + 0 /* queue_idx*/, tbl_size, IONIC_ALIGN, socket_id); + + if (!lif->rss_ind_tbl_z) { + ionic_init_print(ERR, "OOM"); + return -ENOMEM; + } + + lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr; + lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova; + + /* Fill indirection table with 'default' values */ + for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++) + lif->rss_ind_tbl[i] = i % lif->nrxqcqs; + + err = ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL, + toeplitz_symmetric_key, NULL); + if (err) + return err; + + return 0; +} + +static void +ionic_lif_rss_teardown(struct ionic_lif *lif) +{ + if (!lif->rss_ind_tbl) + return; + + if (lif->rss_ind_tbl_z) { + /* Disable RSS on the NIC */ + ionic_lif_rss_config(lif, 0x0, NULL, NULL); + + lif->rss_ind_tbl = NULL; + lif->rss_ind_tbl_pa = 0; + rte_memzone_free(lif->rss_ind_tbl_z); + lif->rss_ind_tbl_z = NULL; + } +} + static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) { @@ -1120,6 +1211,7 @@ ionic_lif_deinit(struct ionic_lif *lif) return; ionic_rx_filters_deinit(lif); + ionic_lif_rss_teardown(lif); ionic_lif_qcq_deinit(lif, lif->notifyqcq); ionic_lif_qcq_deinit(lif, lif->adminqcq); @@ -1129,8 +1221,28 @@ ionic_lif_deinit(struct ionic_lif *lif) int ionic_lif_configure(struct ionic_lif *lif) { + struct ionic_identity *ident = &lif->adapter->ident; + uint32_t ntxqs_per_lif = + ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; + uint32_t nrxqs_per_lif = + ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; + uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues; + uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues; + lif->port_id = lif->eth_dev->data->port_id; + ionic_init_print(DEBUG, "Configuring LIF on port %u", + lif->port_id); + + if (nrxqs > 0) + nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs); + + if (ntxqs > 0) + ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs); + + lif->nrxqcqs = nrxqs_per_lif; + lif->ntxqcqs = ntxqs_per_lif; + return 0; } @@ -1138,6 +1250,14 @@ int ionic_lif_start(struct ionic_lif *lif) { uint32_t rx_mode = 0; + int err; + + ionic_init_print(DEBUG, "Setting RSS configuration on port %u", + lif->port_id); + + err = ionic_lif_rss_setup(lif); + if (err) + return err; ionic_init_print(DEBUG, "Setting RX mode on port %u", lif->port_id); diff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h index e192186a6..faf2f6294 100644 --- a/drivers/net/ionic/ionic_lif.h +++ b/drivers/net/ionic/ionic_lif.h @@ -17,6 +17,14 @@ #define IONIC_ADMINQ_LENGTH 16 /* must be a power of two */ #define IONIC_NOTIFYQ_LENGTH 64 /* must be a power of two */ +#define IONIC_RSS_OFFLOAD_ALL ( \ + IONIC_RSS_TYPE_IPV4 | \ + IONIC_RSS_TYPE_IPV4_TCP | \ + IONIC_RSS_TYPE_IPV4_UDP | \ + IONIC_RSS_TYPE_IPV6 | \ + IONIC_RSS_TYPE_IPV6_TCP | \ + IONIC_RSS_TYPE_IPV6_UDP) + #define IONIC_QCQ_F_INITED BIT(0) #define IONIC_QCQ_F_SG BIT(1) #define IONIC_QCQ_F_INTR BIT(2) @@ -49,6 +57,8 @@ struct ionic_lif { uint32_t index; uint32_t hw_index; uint32_t state; + uint32_t ntxqcqs; + uint32_t nrxqcqs; uint32_t kern_pid; rte_spinlock_t adminq_lock; rte_spinlock_t adminq_service_lock; @@ -62,6 +72,11 @@ struct ionic_lif { uint32_t rx_mode; char name[IONIC_LIF_NAME_MAX_SZ]; uint8_t mac_addr[ETH_ALEN]; + uint16_t rss_types; + uint8_t rss_hash_key[IONIC_RSS_HASH_KEY_SIZE]; + uint8_t *rss_ind_tbl; + rte_iova_t rss_ind_tbl_pa; + const struct rte_memzone *rss_ind_tbl_z; uint32_t info_sz; struct ionic_lif_info *info; rte_iova_t info_pa; @@ -112,6 +127,9 @@ void ionic_qcq_free(struct ionic_qcq *qcq); int ionic_qcq_enable(struct ionic_qcq *qcq); int ionic_qcq_disable(struct ionic_qcq *qcq); +int ionic_lif_rss_config(struct ionic_lif *lif, const uint16_t types, + const uint8_t *key, const uint32_t *indir); + int ionic_lif_set_features(struct ionic_lif *lif); int ionic_notifyq_handler(struct ionic_lif *lif, int budget);