[dpdk-dev] [PATCH v2 4/5] ethdev: allow to get RSS hash functions and key

Ivan Boule ivan.boule at 6wind.com
Fri May 16 10:58:42 CEST 2014


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 |    3 +-
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |    3 ++
 lib/librte_pmd_ixgbe/ixgbe_rxtx.c   |   53 ++++++++++++++++++++++++++++
 11 files changed, 282 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 407a2b9..0b6749c 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 404f84e..614f28f 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 91375a1..dabbdd2 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1594,6 +1594,21 @@ rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *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)
 {
 	struct rte_eth_dev *dev;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index efb421a..43d6a83 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;
 };
 
 /**
@@ -2883,6 +2889,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 d9dc8d1..8790601 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 130ee86..02e0a95 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_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 7ce8d23..6b48df5 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 5a84b3d..79d59ef 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -300,7 +300,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 06d51ab..846db0a 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 c5d9589..c04118c 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)
 {
-- 
1.7.10.4



More information about the dev mailing list