[dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key

Ananyev, Konstantin konstantin.ananyev at intel.com
Fri May 2 01:21:41 CEST 2014


Hi Ivan,

About enabling/disabling RSS dynamically (without dev_stop/dev_start):
As I know 82599 spec explicitly states that RSS shouldn't be enabled/disabled dynamically.
>From section 7.1.2.8 Receive-Side Scaling (RSS):
"...
Enabling rules:
* RSS is enabled in the MRQC register.
* RSS enabling cannot be done dynamically while it must be preceded by a software
reset.
...
Disabling rules:
* Disabling RSS on the fly is not allowed, and the 82599 must be reset after RSS is
disabled.
..."

RETA table from other side can be updated on the fly.
As I remember that was the reason why we allow only dev_rss_reta_update() to be used dynamically (without dev_start/dev_stop).

Konstantin



-----Original Message-----
From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Ivan Boule
Sent: Wednesday, April 30, 2014 2:55 PM
To: dev at dpdk.org
Subject: [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key

1) Add a new function "rss_hash_conf_update" in the PMD API to dynamically
   update the RSS flags and/or 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
   the argument that contains the new hash flags and/or the new hash key to
   use.

2) Add the ixgbe-specific function "ixgbe_dev_rss_hash_conf_update" and the
   igb-specific function "eth_igb_rss_hash_conf_update" to update the RSS
   hash configuration of ixgbe and igb controllers respectively.

Note:
   Configuring the RSS hash flags and the RSS key used by a NIC consists in
   updating appropriate PCI registers of the NIC.
   These operations have been manually tested with the interactive commands
   "write reg" and "write regbit" of the testpmd application.

Signed-off-by: Ivan Boule <ivan.boule at 6wind.com>
---
 lib/librte_ether/rte_ethdev.c       |   23 +++++++++
 lib/librte_ether/rte_ethdev.h       |   25 ++++++++++
 lib/librte_pmd_e1000/e1000_ethdev.h |    3 ++
 lib/librte_pmd_e1000/igb_ethdev.c   |    1 +
 lib/librte_pmd_e1000/igb_rxtx.c     |   93 +++++++++++++++++++++--------------
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c |    1 +
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |    3 ++
 lib/librte_pmd_ixgbe/ixgbe_rxtx.c   |   90 ++++++++++++++++++++-------------
 8 files changed, 169 insertions(+), 70 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 473c98b..c00dff0 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1572,6 +1572,29 @@ rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
 }
 
 int
+rte_eth_dev_rss_hash_conf_update(uint8_t port_id,
+				 struct rte_eth_rss_conf *rss_conf)
+{
+	struct rte_eth_dev *dev;
+	uint16_t rss_hash_protos;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	rss_hash_protos = rss_conf->rss_hf;
+	if ((rss_hash_protos != 0) &&
+	    ((rss_hash_protos & ETH_RSS_PROTO_MASK) == 0)) {
+		PMD_DEBUG_TRACE("Invalid rss_hash_protos=0x%x\n",
+				rss_hash_protos);
+		return (-EINVAL);
+	}
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_conf_update, -ENOTSUP);
+	return (*dev->dev_ops->rss_hash_conf_update)(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 dea7471..a970761 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -331,6 +331,8 @@ struct rte_eth_rss_conf {
 #define ETH_RSS_IPV4_UDP    0x0040 /**< IPv4/UDP packet. */
 #define ETH_RSS_IPV6_UDP    0x0080 /**< IPv6/UDP packet. */
 #define ETH_RSS_IPV6_UDP_EX 0x0100 /**< IPv6/UDP with extension headers. */
+
+#define ETH_RSS_PROTO_MASK  0x01FF /**< Mask of valid RSS hash protocols */
 /* Definitions used for redirection table entry size */
 #define ETH_RSS_RETA_NUM_ENTRIES 128
 #define ETH_RSS_RETA_MAX_QUEUE   16  
@@ -966,6 +968,10 @@ typedef int (*reta_query_t)(struct rte_eth_dev *dev,
 				struct rte_eth_rss_reta *reta_conf);
 /**< @internal Query RSS redirection table on an Ethernet device */
 
+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 (*eth_dev_led_on_t)(struct rte_eth_dev *dev);
 /**< @internal Turn on SW controllable LED on an Ethernet device */
 
@@ -1153,6 +1159,8 @@ struct eth_dev_ops {
   bypass_wd_reset_t bypass_wd_reset;
 #endif
 
+	/** Configure RSS hash protocols. */
+	rss_hash_conf_update_t rss_hash_conf_update;
 };
 
 /**
@@ -2859,6 +2867,23 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
  */
 int rte_eth_dev_bypass_wd_reset(uint8_t port);
 
+ /**
+ * Configuration of Receive Side Scaling hash computation of Ethernet device.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param rss_conf
+ *   The new configuration to use for RSS hash computation on the port.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_rss_hash_conf_update(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 d09064e..e228c53 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -138,6 +138,9 @@ uint16_t eth_igb_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
 uint16_t eth_igb_recv_scattered_pkts(void *rxq,
 		struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
 
+int eth_igb_rss_hash_conf_update(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 673b4de..07ae149 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -193,6 +193,7 @@ static struct eth_dev_ops eth_igb_ops = {
 	.mac_addr_remove      = eth_igb_rar_clear,
 	.reta_update          = eth_igb_rss_reta_update,
 	.reta_query           = eth_igb_rss_reta_query,
+	.rss_hash_conf_update = eth_igb_rss_hash_conf_update,
 };
 
 /*
diff --git a/lib/librte_pmd_e1000/igb_rxtx.c b/lib/librte_pmd_e1000/igb_rxtx.c
index 1ebe2f5..5499fd8 100644
--- a/lib/librte_pmd_e1000/igb_rxtx.c
+++ b/lib/librte_pmd_e1000/igb_rxtx.c
@@ -1518,54 +1518,36 @@ igb_rss_disable(struct rte_eth_dev *dev)
 	E1000_WRITE_REG(hw, E1000_MRQC, mrqc);
 }
 
-static void
-igb_rss_configure(struct rte_eth_dev *dev)
+int
+eth_igb_rss_hash_conf_update(struct rte_eth_dev *dev,
+			     struct rte_eth_rss_conf *rss_conf)
 {
 	struct e1000_hw *hw;
-	uint8_t *hash_key;
+	uint8_t  *hash_key;
 	uint32_t rss_key;
 	uint32_t mrqc;
-	uint32_t shift;
 	uint16_t rss_hf;
 	uint16_t i;
 
 	hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
-	if (rss_hf == 0) /* Disable RSS. */ {
-		igb_rss_disable(dev);
-		return;
-	}
-	hash_key = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
-	if (hash_key == NULL)
-		hash_key = rss_intel_key; /* Default hash key. */
-
-	/* Fill in RSS hash key. */
-	for (i = 0; i < 10; i++) {
-		rss_key  = hash_key[(i * 4)];
-		rss_key |= hash_key[(i * 4) + 1] << 8;
-		rss_key |= hash_key[(i * 4) + 2] << 16;
-		rss_key |= hash_key[(i * 4) + 3] << 24;
-		E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), i, rss_key);
+	hash_key = rss_conf->rss_key;
+	if (hash_key != NULL) {
+		/* Fill in RSS hash key */
+		for (i = 0; i < 10; i++) {
+			rss_key  = hash_key[(i * 4)];
+			rss_key |= hash_key[(i * 4) + 1] << 8;
+			rss_key |= hash_key[(i * 4) + 2] << 16;
+			rss_key |= hash_key[(i * 4) + 3] << 24;
+			E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), i, rss_key);
+		}
 	}
-
-	/* Fill in redirection table. */
-	shift = (hw->mac.type == e1000_82575) ? 6 : 0;
-	for (i = 0; i < 128; i++) {
-		union e1000_reta {
-			uint32_t dword;
-			uint8_t  bytes[4];
-		} reta;
-		uint8_t q_idx;
-
-		q_idx = (uint8_t) ((dev->data->nb_rx_queues > 1) ?
-				   i % dev->data->nb_rx_queues : 0);
-		reta.bytes[i & 3] = (uint8_t) (q_idx << shift);
-		if ((i & 3) == 3)
-			E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword);
+	rss_hf = rss_conf->rss_hf;
+	if (rss_hf == 0) { /* Disable RSS */
+		igb_rss_disable(dev);
+		return 0;
 	}
 
-	/* Set configured hashing functions in MRQC register. */
+	/* Set configured hashing protocols in MRQC register */
 	mrqc = E1000_MRQC_ENABLE_RSS_4Q; /* RSS enabled. */
 	if (rss_hf & ETH_RSS_IPV4)
 		mrqc |= E1000_MRQC_RSS_FIELD_IPV4;
@@ -1586,6 +1568,43 @@ igb_rss_configure(struct rte_eth_dev *dev)
 	if (rss_hf & ETH_RSS_IPV6_UDP_EX)
 		mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP_EX;
 	E1000_WRITE_REG(hw, E1000_MRQC, mrqc);
+	return 0;
+}
+
+static void
+igb_rss_configure(struct rte_eth_dev *dev)
+{
+	struct rte_eth_rss_conf rss_conf;
+	struct e1000_hw *hw;
+	uint32_t shift;
+	uint16_t i;
+
+	hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	/* Fill in redirection table. */
+	shift = (hw->mac.type == e1000_82575) ? 6 : 0;
+	for (i = 0; i < 128; i++) {
+		union e1000_reta {
+			uint32_t dword;
+			uint8_t  bytes[4];
+		} reta;
+		uint8_t q_idx;
+
+		q_idx = (uint8_t) ((dev->data->nb_rx_queues > 1) ?
+				   i % dev->data->nb_rx_queues : 0);
+		reta.bytes[i & 3] = (uint8_t) (q_idx << shift);
+		if ((i & 3) == 3)
+			E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword);
+	}
+
+	/*
+	 * Configure the RSS key and the RSS protocols used to compute
+	 * the RSS hash of input packets.
+	 */
+	rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
+	if (rss_conf.rss_key == NULL)
+		rss_conf.rss_key = rss_intel_key; /* Default hash key */
+	(void) eth_igb_rss_hash_conf_update(dev, &rss_conf);
 }
 
 /*
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 6dd52d7..5910501 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -300,6 +300,7 @@ 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_conf_update = ixgbe_dev_rss_hash_conf_update,
 };
 
 /*
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..3d33ad2 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -235,6 +235,9 @@ uint16_t ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
 		uint16_t nb_pkts);
 
+int ixgbe_dev_rss_hash_conf_update(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 7930dbd..877ecfd 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
@@ -2291,50 +2291,37 @@ ixgbe_rss_disable(struct rte_eth_dev *dev)
 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
 }
 
-static void
-ixgbe_rss_configure(struct rte_eth_dev *dev)
+int
+ixgbe_dev_rss_hash_conf_update(struct rte_eth_dev *dev,
+			       struct rte_eth_rss_conf *rss_conf)
 {
 	struct ixgbe_hw *hw;
-	uint8_t *hash_key;
-	uint32_t rss_key;
+	uint8_t  *hash_key;
 	uint32_t mrqc;
-	uint32_t reta;
+	uint32_t rss_key;
 	uint16_t rss_hf;
 	uint16_t i;
-	uint16_t j;
 
-	PMD_INIT_FUNC_TRACE();
 	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
+	hash_key = rss_conf->rss_key;
+	if (hash_key != NULL) {
+		/* Fill in RSS hash key */
+		for (i = 0; i < 10; i++) {
+			rss_key  = hash_key[(i * 4)];
+			rss_key |= hash_key[(i * 4) + 1] << 8;
+			rss_key |= hash_key[(i * 4) + 2] << 16;
+			rss_key |= hash_key[(i * 4) + 3] << 24;
+			IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, rss_key);
+		}
+	}
+	rss_hf = rss_conf->rss_hf;
 	if (rss_hf == 0) { /* Disable RSS */
 		ixgbe_rss_disable(dev);
-		return;
-	}
-	hash_key = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
-	if (hash_key == NULL)
-		hash_key = rss_intel_key; /* Default hash key */
-
-	/* Fill in RSS hash key */
-	for (i = 0; i < 10; i++) {
-		rss_key  = hash_key[(i * 4)];
-		rss_key |= hash_key[(i * 4) + 1] << 8;
-		rss_key |= hash_key[(i * 4) + 2] << 16;
-		rss_key |= hash_key[(i * 4) + 3] << 24;
-		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, rss_key);
-	}
-
-	/* Fill in redirection table */
-	reta = 0;
-	for (i = 0, j = 0; i < 128; i++, j++) {
-		if (j == dev->data->nb_rx_queues) j = 0;
-		reta = (reta << 8) | j;
-		if ((i & 3) == 3)
-			IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), rte_bswap32(reta));
+		return 0;
 	}
 
-	/* Set configured hashing functions in MRQC register */
-	mrqc = IXGBE_MRQC_RSSEN; /* RSS enable */
+	/* Set configured hashing protocols in MRQC register */
+	mrqc = IXGBE_MRQC_RSSEN; /* Enable RSS */
 	if (rss_hf & ETH_RSS_IPV4)
 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
 	if (rss_hf & ETH_RSS_IPV4_TCP)
@@ -2354,6 +2341,43 @@ ixgbe_rss_configure(struct rte_eth_dev *dev)
 	if (rss_hf & ETH_RSS_IPV6_UDP_EX)
 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+	return 0;
+}
+
+static void
+ixgbe_rss_configure(struct rte_eth_dev *dev)
+{
+	struct rte_eth_rss_conf rss_conf;
+	struct ixgbe_hw *hw;
+	uint32_t reta;
+	uint16_t i;
+	uint16_t j;
+
+	PMD_INIT_FUNC_TRACE();
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	/*
+	 * Fill in redirection table
+	 * The byte-swap is needed because NIC registers are in
+	 * little-endian order.
+	 */
+	reta = 0;
+	for (i = 0, j = 0; i < 128; i++, j++) {
+		if (j == dev->data->nb_rx_queues) j = 0;
+		reta = (reta << 8) | j;
+		if ((i & 3) == 3)
+			IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2),
+					rte_bswap32(reta));
+	}
+
+	/*
+	 * Configure the RSS key and the RSS protocols used to compute
+	 * the RSS hash of input packets.
+	 */
+	rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
+	if (rss_conf.rss_key == NULL)
+		rss_conf.rss_key = rss_intel_key; /* Default hash key */
+	(void) ixgbe_dev_rss_hash_conf_update(dev, &rss_conf);
 }
 
 #define NUM_VFTA_REGISTERS 128
-- 
1.7.10.4



More information about the dev mailing list