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 <ivan.boule at 6wind.com>
---
 app/test-pmd/cmdline.c              |   63 +++++++++++++++++++++++++++++++++
 app/test-pmd/config.c               |   65 +++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h              |    2 ++
 lib/librte_ether/rte_ethdev.c       |   15 ++++++++
 lib/librte_ether/rte_ethdev.h       |   23 +++++++++++++
 lib/librte_pmd_e1000/e1000_ethdev.h |    3 ++
 lib/librte_pmd_e1000/igb_ethdev.c   |    1 +
 lib/librte_pmd_e1000/igb_rxtx.c     |   52 ++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c |    1 +
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |    3 ++
 lib/librte_pmd_ixgbe/ixgbe_rxtx.c   |   53 ++++++++++++++++++++++++++++
 11 files changed, 281 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index e06379c..3454c0b 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"

@@ -1364,6 +1368,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;
@@ -5259,6 +5320,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 5905fea..1e332a9 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -682,6 +682,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.
  */
 static void
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ffd3495..b9d47c4 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -523,6 +523,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 c00dff0..2f491e2 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1595,6 +1595,21 @@ rte_eth_dev_rss_hash_conf_update(uint8_t port_id,
 }

 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)
 {
        struct rte_eth_dev *dev;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index a970761..1d62413 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -972,6 +972,10 @@ typedef int (*rss_hash_conf_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_conf_update_t rss_hash_conf_update;
+       /** Get current RSS hash configuration. */
+       rss_hash_conf_get_t rss_hash_conf_get;
 };

 /**
@@ -2884,6 +2890,23 @@ int
 rte_eth_dev_rss_hash_conf_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 e228c53..58e3420 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_conf_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 07ae149..3c476f3 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -194,6 +194,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_conf_update = eth_igb_rss_hash_conf_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 5499fd8..c420075 100644
--- a/lib/librte_pmd_e1000/igb_rxtx.c
+++ b/lib/librte_pmd_e1000/igb_rxtx.c
@@ -1571,6 +1571,58 @@ eth_igb_rss_hash_conf_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 5910501..44c75b3 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -301,6 +301,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
        .bypass_wd_reset      = ixgbe_bypass_wd_reset,
 #endif /* RTE_NIC_BYPASS */
        .rss_hash_conf_update = ixgbe_dev_rss_hash_conf_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 3d33ad2..9746857 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_conf_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 877ecfd..03eb650 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
@@ -2344,6 +2344,59 @@ ixgbe_dev_rss_hash_conf_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)
 {
-- 
1.7.10.4

Reply via email to