From: Ivan Boule Date: Fri, 16 May 2014 08:58:42 +0000 (+0200) Subject: ethdev: allow to get RSS hash functions and key X-Git-Tag: spdx-start~10781 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=16321de09396eaef80881b4573d4b7fb87a49ea7;p=dpdk.git ethdev: allow to get RSS hash functions and key 1) Add a new function "rss_hash_conf_get" in the PMD API to retrieve the current configuration of the RSS functions and/or of the RSS key used by a NIC to compute the RSS hash of input packets. The new function uses the existing data structure "rte_eth_rss_conf" for returning the RSS hash configuration. 2) Add the ixgbe-specific function "ixgbe_dev_rss_hash_conf_get" and the igb-specific function "eth_igb_rss_hash_conf_get" to retrieve the RSS hash configuration of ixgbe and igb controllers respectively. 3) Add the command "show port X rss-hash [key]" in the testpmd application to display the RSS hash configuration of port X. Signed-off-by: Ivan Boule Acked-by: Thomas Monjalon --- diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 6a79d6cdf7..43c8ca050a 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -182,6 +182,10 @@ static void cmd_help_long_parsed(void *parsed_result, "show port (info|stats|fdir|stat_qmap) (port_id|all)\n" " Display information for port_id, or all.\n\n" + "show port rss-hash [key]\n" + " Display the RSS hash functions and RSS hash key" + " of port X\n\n" + "clear port (info|stats|fdir|stat_qmap) (port_id|all)\n" " Clear information for port_id, or all.\n\n" @@ -1343,6 +1347,63 @@ cmdline_parse_inst_t cmd_showport_reta = { }, }; +/* *** Show RSS hash configuration *** */ +struct cmd_showport_rss_hash { + cmdline_fixed_string_t show; + cmdline_fixed_string_t port; + uint8_t port_id; + cmdline_fixed_string_t rss_hash; + cmdline_fixed_string_t key; /* optional argument */ +}; + +static void cmd_showport_rss_hash_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *show_rss_key) +{ + struct cmd_showport_rss_hash *res = parsed_result; + + port_rss_hash_conf_show(res->port_id, show_rss_key != NULL); +} + +cmdline_parse_token_string_t cmd_showport_rss_hash_show = + TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, show, "show"); +cmdline_parse_token_string_t cmd_showport_rss_hash_port = + TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, port, "port"); +cmdline_parse_token_num_t cmd_showport_rss_hash_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_showport_rss_hash, port_id, UINT8); +cmdline_parse_token_string_t cmd_showport_rss_hash_rss_hash = + TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, rss_hash, + "rss-hash"); +cmdline_parse_token_string_t cmd_showport_rss_hash_rss_key = + TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, key, "key"); + +cmdline_parse_inst_t cmd_showport_rss_hash = { + .f = cmd_showport_rss_hash_parsed, + .data = NULL, + .help_str = "show port X rss-hash (X = port number)\n", + .tokens = { + (void *)&cmd_showport_rss_hash_show, + (void *)&cmd_showport_rss_hash_port, + (void *)&cmd_showport_rss_hash_port_id, + (void *)&cmd_showport_rss_hash_rss_hash, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_showport_rss_hash_key = { + .f = cmd_showport_rss_hash_parsed, + .data = "show_rss_key", + .help_str = "show port X rss-hash key (X = port number)\n", + .tokens = { + (void *)&cmd_showport_rss_hash_show, + (void *)&cmd_showport_rss_hash_port, + (void *)&cmd_showport_rss_hash_port_id, + (void *)&cmd_showport_rss_hash_rss_hash, + (void *)&cmd_showport_rss_hash_rss_key, + NULL, + }, +}; + /* *** Configure DCB *** */ struct cmd_config_dcb { cmdline_fixed_string_t port; @@ -5229,6 +5290,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_mirror_mask, (cmdline_parse_inst_t *)&cmd_set_mirror_link, (cmdline_parse_inst_t *)&cmd_reset_mirror_rule, + (cmdline_parse_inst_t *)&cmd_showport_rss_hash, + (cmdline_parse_inst_t *)&cmd_showport_rss_hash_key, (cmdline_parse_inst_t *)&cmd_dump, (cmdline_parse_inst_t *)&cmd_dump_one, NULL, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 20ad0a81ba..d12f46c037 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -681,6 +681,71 @@ port_rss_reta_info(portid_t port_id,struct rte_eth_rss_reta *reta_conf) } } +/* + * Displays the RSS hash functions of a port, and, optionaly, the RSS hash + * key of the port. + */ +void +port_rss_hash_conf_show(portid_t port_id, int show_rss_key) +{ + struct rte_eth_rss_conf rss_conf; + uint8_t rss_key[10 * 4]; + uint16_t rss_hf; + uint8_t i; + int diag; + + if (port_id_is_invalid(port_id)) + return; + /* Get RSS hash key if asked to display it */ + rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; + diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); + if (diag != 0) { + switch (diag) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + default: + printf("operation failed - diag=%d\n", diag); + break; + } + return; + } + rss_hf = rss_conf.rss_hf; + if (rss_hf == 0) { + printf("RSS disabled\n"); + return; + } + printf("RSS functions:\n "); + if (rss_hf & ETH_RSS_IPV4) + printf("ip4"); + if (rss_hf & ETH_RSS_IPV4_TCP) + printf(" tcp4"); + if (rss_hf & ETH_RSS_IPV4_UDP) + printf(" udp4"); + if (rss_hf & ETH_RSS_IPV6) + printf(" ip6"); + if (rss_hf & ETH_RSS_IPV6_EX) + printf(" ip6-ex"); + if (rss_hf & ETH_RSS_IPV6_TCP) + printf(" tcp6"); + if (rss_hf & ETH_RSS_IPV6_TCP_EX) + printf(" tcp6-ex"); + if (rss_hf & ETH_RSS_IPV6_UDP) + printf(" udp6"); + if (rss_hf & ETH_RSS_IPV6_UDP_EX) + printf(" udp6-ex"); + printf("\n"); + if (!show_rss_key) + return; + printf("RSS key:\n"); + for (i = 0; i < sizeof(rss_key); i++) + printf("%02X", rss_key[i]); + printf("\n"); +} + /* * Setup forwarding configuration for each logical core. */ diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 2bdb1a206b..af853cb585 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -528,6 +528,8 @@ void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on); void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on); +void port_rss_hash_conf_show(portid_t port_id, int show_rss_key); + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 91375a12e7..dabbdd25b6 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1593,6 +1593,21 @@ rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *rss_conf) return (*dev->dev_ops->rss_hash_update)(dev, rss_conf); } +int +rte_eth_dev_rss_hash_conf_get(uint8_t port_id, + struct rte_eth_rss_conf *rss_conf) +{ + struct rte_eth_dev *dev; + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return (-ENODEV); + } + dev = &rte_eth_devices[port_id]; + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_conf_get, -ENOTSUP); + return (*dev->dev_ops->rss_hash_conf_get)(dev, rss_conf); +} + int rte_eth_led_on(uint8_t port_id) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index e4ad9a7ad9..4bf2383bd9 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -972,6 +972,10 @@ typedef int (*rss_hash_update_t)(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); /**< @internal Update RSS hash configuration of an Ethernet device */ +typedef int (*rss_hash_conf_get_t)(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf); +/**< @internal Get current RSS hash configuration of an Ethernet device */ + typedef int (*eth_dev_led_on_t)(struct rte_eth_dev *dev); /**< @internal Turn on SW controllable LED on an Ethernet device */ @@ -1161,6 +1165,8 @@ struct eth_dev_ops { /** Configure RSS hash protocols. */ rss_hash_update_t rss_hash_update; + /** Get current RSS hash configuration. */ + rss_hash_conf_get_t rss_hash_conf_get; }; /** @@ -2749,6 +2755,23 @@ int rte_eth_dev_bypass_wd_reset(uint8_t port); int rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *rss_conf); + /** + * Retrieve current configuration of Receive Side Scaling hash computation + * of Ethernet device. + * + * @param port + * The port identifier of the Ethernet device. + * @param rss_conf + * Where to store the current RSS hash configuration of the Ethernet device. + * @return + * - (0) if successful. + * - (-ENODEV) if port identifier is invalid. + * - (-ENOTSUP) if hardware doesn't support RSS. + */ +int +rte_eth_dev_rss_hash_conf_get(uint8_t port_id, + struct rte_eth_rss_conf *rss_conf); + #ifdef __cplusplus } #endif diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h index d9dc8d1eca..87906010ec 100644 --- a/lib/librte_pmd_e1000/e1000_ethdev.h +++ b/lib/librte_pmd_e1000/e1000_ethdev.h @@ -141,6 +141,9 @@ uint16_t eth_igb_recv_scattered_pkts(void *rxq, int eth_igb_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); +int eth_igb_rss_hash_conf_get(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf); + int eth_igbvf_rx_init(struct rte_eth_dev *dev); void eth_igbvf_tx_init(struct rte_eth_dev *dev); diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c index 92794c87f1..5f93bcf80d 100644 --- a/lib/librte_pmd_e1000/igb_ethdev.c +++ b/lib/librte_pmd_e1000/igb_ethdev.c @@ -195,6 +195,7 @@ static struct eth_dev_ops eth_igb_ops = { .reta_update = eth_igb_rss_reta_update, .reta_query = eth_igb_rss_reta_query, .rss_hash_update = eth_igb_rss_hash_update, + .rss_hash_conf_get = eth_igb_rss_hash_conf_get, }; /* diff --git a/lib/librte_pmd_e1000/igb_rxtx.c b/lib/librte_pmd_e1000/igb_rxtx.c index 963770408b..ae53428672 100644 --- a/lib/librte_pmd_e1000/igb_rxtx.c +++ b/lib/librte_pmd_e1000/igb_rxtx.c @@ -1593,6 +1593,58 @@ eth_igb_rss_hash_update(struct rte_eth_dev *dev, return 0; } +int eth_igb_rss_hash_conf_get(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct e1000_hw *hw; + uint8_t *hash_key; + uint32_t rss_key; + uint32_t mrqc; + uint16_t rss_hf; + uint16_t i; + + hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + hash_key = rss_conf->rss_key; + if (hash_key != NULL) { + /* Return RSS hash key */ + for (i = 0; i < 10; i++) { + rss_key = E1000_READ_REG_ARRAY(hw, E1000_RSSRK(0), i); + hash_key[(i * 4)] = rss_key & 0x000000FF; + hash_key[(i * 4) + 1] = (rss_key >> 8) & 0x000000FF; + hash_key[(i * 4) + 2] = (rss_key >> 16) & 0x000000FF; + hash_key[(i * 4) + 3] = (rss_key >> 24) & 0x000000FF; + } + } + + /* Get RSS functions configured in MRQC register */ + mrqc = E1000_READ_REG(hw, E1000_MRQC); + if ((mrqc & E1000_MRQC_ENABLE_RSS_4Q) == 0) { /* RSS is disabled */ + rss_conf->rss_hf = 0; + return 0; + } + rss_hf = 0; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) + rss_hf |= ETH_RSS_IPV4; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) + rss_hf |= ETH_RSS_IPV4_TCP; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) + rss_hf |= ETH_RSS_IPV6; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_EX) + rss_hf |= ETH_RSS_IPV6_EX; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) + rss_hf |= ETH_RSS_IPV6_TCP; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP_EX) + rss_hf |= ETH_RSS_IPV6_TCP_EX; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_UDP) + rss_hf |= ETH_RSS_IPV4_UDP; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_UDP) + rss_hf |= ETH_RSS_IPV6_UDP; + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_UDP_EX) + rss_hf |= ETH_RSS_IPV6_UDP_EX; + rss_conf->rss_hf = rss_hf; + return 0; +} + static void igb_rss_configure(struct rte_eth_dev *dev) { diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index 0b81f2b6de..761b961a25 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -307,7 +307,8 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .bypass_ver_show = ixgbe_bypass_ver_show, .bypass_wd_reset = ixgbe_bypass_wd_reset, #endif /* RTE_NIC_BYPASS */ - .rss_hash_update = ixgbe_dev_rss_hash_update, + .rss_hash_update = ixgbe_dev_rss_hash_update, + .rss_hash_conf_get = ixgbe_dev_rss_hash_conf_get, }; /* diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h index 06d51ab01f..846db0ae09 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h @@ -238,6 +238,9 @@ uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, int ixgbe_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); +int ixgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf); + /* * Flow director function prototypes */ diff --git a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c index 111d1fa21d..9f3002534b 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c +++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c @@ -2369,6 +2369,59 @@ ixgbe_dev_rss_hash_update(struct rte_eth_dev *dev, return 0; } +int +ixgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf) +{ + struct ixgbe_hw *hw; + uint8_t *hash_key; + uint32_t mrqc; + uint32_t rss_key; + uint16_t rss_hf; + uint16_t i; + + hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + hash_key = rss_conf->rss_key; + if (hash_key != NULL) { + /* Return RSS hash key */ + for (i = 0; i < 10; i++) { + rss_key = IXGBE_READ_REG_ARRAY(hw, IXGBE_RSSRK(0), i); + hash_key[(i * 4)] = rss_key & 0x000000FF; + hash_key[(i * 4) + 1] = (rss_key >> 8) & 0x000000FF; + hash_key[(i * 4) + 2] = (rss_key >> 16) & 0x000000FF; + hash_key[(i * 4) + 3] = (rss_key >> 24) & 0x000000FF; + } + } + + /* Get RSS functions configured in MRQC register */ + mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); + if ((mrqc & IXGBE_MRQC_RSSEN) == 0) { /* RSS is disabled */ + rss_conf->rss_hf = 0; + return 0; + } + rss_hf = 0; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4) + rss_hf |= ETH_RSS_IPV4; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_TCP) + rss_hf |= ETH_RSS_IPV4_TCP; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6) + rss_hf |= ETH_RSS_IPV6; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX) + rss_hf |= ETH_RSS_IPV6_EX; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_TCP) + rss_hf |= ETH_RSS_IPV6_TCP; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP) + rss_hf |= ETH_RSS_IPV6_TCP_EX; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_UDP) + rss_hf |= ETH_RSS_IPV4_UDP; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_UDP) + rss_hf |= ETH_RSS_IPV6_UDP; + if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP) + rss_hf |= ETH_RSS_IPV6_UDP_EX; + rss_conf->rss_hf = rss_hf; + return 0; +} + static void ixgbe_rss_configure(struct rte_eth_dev *dev) {