DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration
@ 2014-04-30 13:55 Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 1/5] ethdev: check RX queue indices in RETA config against number of queues Ivan Boule
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

This set of patches allows to dynamically get and set the RSS configuration of a
port:
- rss functions (IP/UDP/TCP ...)
- rss hash key

-- 
Ivan Boule

Ivan Boule (5):
  ethdev: check RX queue indices in RETA config against number of
    queues
  ethdev: allow to set RSS hash computation flags and/or key
  app/testpmd: configure RSS without restart
  ethdev: allow to get RSS hash functions and key
  app/testpmd: allow to configure RSS hash key

 app/test-pmd/cmdline.c              |  177 ++++++++++++++++++++++++++++++++---
 app/test-pmd/config.c               |   93 ++++++++++++++++++
 app/test-pmd/testpmd.h              |    3 +
 lib/librte_ether/rte_ethdev.c       |   48 +++++++++-
 lib/librte_ether/rte_ethdev.h       |   48 ++++++++++
 lib/librte_pmd_e1000/e1000_ethdev.h |    6 ++
 lib/librte_pmd_e1000/igb_ethdev.c   |    2 +
 lib/librte_pmd_e1000/igb_rxtx.c     |  145 ++++++++++++++++++++--------
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c |    2 +
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |    6 ++
 lib/librte_pmd_ixgbe/ixgbe_rxtx.c   |  143 +++++++++++++++++++++-------
 11 files changed, 587 insertions(+), 86 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH 1/5] ethdev: check RX queue indices in RETA config against number of queues
  2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
@ 2014-04-30 13:55 ` Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key Ivan Boule
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

Each entry of the RSS redirection table (RETA) of igb and ixgbe ports
contains a 4-bit RX queue index, thus imposing RSS RX queue indices to
be strictly lower than 16.
In addition, if a RETA entry is configured with a RX queue index that is
strictly lower than 16, but is greater or equal to the number of RX queues
of the port, then all input packets whose RSS hash value indexes that RETA
entry are silently dropped by the NIC.

Make the function rte_eth_dev_rss_reta_update() check that RX queue indices
that are supplied in the reta_conf argument are strictly lower than
ETH_RSS_RETA_MAX_QUEUE (16) and are strictly lower than the number of
RX queues of the port.

Signed-off-by: Ivan Boule <ivan.boule@6wind.com>
---
 lib/librte_ether/rte_ethdev.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a5727dd..473c98b 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1501,6 +1501,7 @@ int
 rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
 {
 	struct rte_eth_dev *dev;
+	uint16_t max_rxq;
 	uint8_t i,j;
 
 	if (port_id >= nb_ports) {
@@ -1514,10 +1515,13 @@ rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
 		return (-EINVAL);
 	}
 
+	dev = &rte_eth_devices[port_id];
+	max_rxq = (dev->data->nb_rx_queues <= ETH_RSS_RETA_MAX_QUEUE) ?
+		dev->data->nb_rx_queues : ETH_RSS_RETA_MAX_QUEUE;
 	if (reta_conf->mask_lo != 0) {
 		for (i = 0; i < ETH_RSS_RETA_NUM_ENTRIES/2; i++) {
 			if ((reta_conf->mask_lo & (1ULL << i)) &&
-				(reta_conf->reta[i] >= ETH_RSS_RETA_MAX_QUEUE)) {
+				(reta_conf->reta[i] >= max_rxq)) {
 				PMD_DEBUG_TRACE("RETA hash index output"
 					"configration for port=%d,invalid"
 					"queue=%d\n",port_id,reta_conf->reta[i]);
@@ -1533,7 +1537,7 @@ rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
 
 			/* Check if the max entry >= 128 */
 			if ((reta_conf->mask_hi & (1ULL << i)) && 
-				(reta_conf->reta[j] >= ETH_RSS_RETA_MAX_QUEUE)) {
+				(reta_conf->reta[j] >= max_rxq)) {
 				PMD_DEBUG_TRACE("RETA hash index output"
 					"configration for port=%d,invalid"
 					"queue=%d\n",port_id,reta_conf->reta[j]);
@@ -1543,8 +1547,6 @@ rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
 		}
 	}
 
-	dev = &rte_eth_devices[port_id];
-
 	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_update, -ENOTSUP);
 	return (*dev->dev_ops->reta_update)(dev, reta_conf);
 }
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key
  2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 1/5] ethdev: check RX queue indices in RETA config against number of queues Ivan Boule
@ 2014-04-30 13:55 ` Ivan Boule
  2014-05-01 23:21   ` Ananyev, Konstantin
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 3/5] app/testpmd: configure RSS without restart Ivan Boule
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

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@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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH 3/5] app/testpmd: configure RSS without restart
  2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 1/5] ethdev: check RX queue indices in RETA config against number of queues Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key Ivan Boule
@ 2014-04-30 13:55 ` Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 4/5] ethdev: allow to get RSS hash functions and key Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 5/5] app/testpmd: allow to configure RSS hash key Ivan Boule
  4 siblings, 0 replies; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

The function cmd_config_rss_parsed() associated with the command
"port config rss all" required to first stop all ports, in order to
then entirely re-configure all ports with the new RSS hash computation
parameters.
Use now the new function rte_eth_dev_rss_hash_conf_update() that dynamically
only changes the RSS hash computation parameters of a port, without needing
to previously stop the port.

Signed-off-by: Ivan Boule <ivan.boule@6wind.com>
---
 app/test-pmd/cmdline.c |   20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 9cc680f..e06379c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1145,26 +1145,22 @@ cmd_config_rss_parsed(void *parsed_result,
 			__attribute__((unused)) void *data)
 {
 	struct cmd_config_rss *res = parsed_result;
-
-	if (!all_ports_stopped()) {
-		printf("Please stop all ports first\n");
-		return;
-	}
+	struct rte_eth_rss_conf rss_conf;
+	uint8_t i;
 
 	if (!strcmp(res->value, "ip"))
-		rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6;
+		rss_conf.rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6;
 	else if (!strcmp(res->value, "udp"))
-		rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6 | ETH_RSS_IPV4_UDP;
+		rss_conf.rss_hf = ETH_RSS_IPV4_UDP | ETH_RSS_IPV6_UDP;
 	else if (!strcmp(res->value, "none"))
-		rss_hf = 0;
+		rss_conf.rss_hf = 0;
 	else {
 		printf("Unknown parameter\n");
 		return;
 	}
-
-	init_port_config();
-
-	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+	rss_conf.rss_key = NULL;
+	for (i = 0; i < rte_eth_dev_count(); i++)
+		rte_eth_dev_rss_hash_conf_update(i, &rss_conf);
 }
 
 cmdline_parse_token_string_t cmd_config_rss_port =
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH 4/5] ethdev: allow to get RSS hash functions and key
  2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
                   ` (2 preceding siblings ...)
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 3/5] app/testpmd: configure RSS without restart Ivan Boule
@ 2014-04-30 13:55 ` Ivan Boule
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 5/5] app/testpmd: allow to configure RSS hash key Ivan Boule
  4 siblings, 0 replies; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

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@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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH 5/5] app/testpmd: allow to configure RSS hash key
  2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
                   ` (3 preceding siblings ...)
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 4/5] ethdev: allow to get RSS hash functions and key Ivan Boule
@ 2014-04-30 13:55 ` Ivan Boule
  4 siblings, 0 replies; 9+ messages in thread
From: Ivan Boule @ 2014-04-30 13:55 UTC (permalink / raw)
  To: dev

Add the command "port config X rss-hash-key key" in the 'testpmd'
application to configure the RSS hash key used to compute the RSS
hash of input [IP] packets received on port X.

Signed-off-by: Ivan Boule <ivan.boule@6wind.com>
---
 app/test-pmd/cmdline.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c  |   28 ++++++++++++++
 app/test-pmd/testpmd.h |    1 +
 3 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 3454c0b..d561bf3 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1192,6 +1192,99 @@ cmdline_parse_inst_t cmd_config_rss = {
 	},
 };
 
+/* *** configure rss hash key *** */
+struct cmd_config_rss_hash_key {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	uint8_t port_id;
+	cmdline_fixed_string_t rss_hash_key;
+	cmdline_fixed_string_t key;
+};
+
+#define RSS_HASH_KEY_LENGTH 40
+static uint8_t
+hexa_digit_to_value(char hexa_digit)
+{
+	if ((hexa_digit >= '0') && (hexa_digit <= '9'))
+		return (uint8_t) (hexa_digit - '0');
+	if ((hexa_digit >= 'a') && (hexa_digit <= 'f'))
+		return (uint8_t) ((hexa_digit - 'a') + 10);
+	if ((hexa_digit >= 'A') && (hexa_digit <= 'F'))
+		return (uint8_t) ((hexa_digit - 'A') + 10);
+	/* Invalid hexa digit */
+	return 0xFF;
+}
+
+static uint8_t
+parse_and_check_key_hexa_digit(char *key, int idx)
+{
+	uint8_t hexa_v;
+
+	hexa_v = hexa_digit_to_value(key[idx]);
+	if (hexa_v == 0xFF)
+		printf("invalid key: character %c at position %d is not a "
+		       "valid hexa digit\n", key[idx], idx);
+	return hexa_v;
+}
+
+static void
+cmd_config_rss_hash_key_parsed(void *parsed_result,
+			       __attribute__((unused)) struct cmdline *cl,
+			       __attribute__((unused)) void *data)
+{
+	struct cmd_config_rss_hash_key *res = parsed_result;
+	uint8_t hash_key[RSS_HASH_KEY_LENGTH];
+	uint8_t xdgt0;
+	uint8_t xdgt1;
+	int i;
+
+	/* Check the length of the RSS hash key */
+	if (strlen(res->key) != (RSS_HASH_KEY_LENGTH * 2)) {
+		printf("key length: %d invalid - key must be a string of %d"
+		       "hexa-decimal numbers\n", (int) strlen(res->key),
+		       RSS_HASH_KEY_LENGTH * 2);
+		return;
+	}
+	/* Translate RSS hash key into binary representation */
+	for (i = 0; i < RSS_HASH_KEY_LENGTH; i++) {
+		xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+		if (xdgt0 == 0xFF)
+			return;
+		xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+		if (xdgt1 == 0xFF)
+			return;
+		hash_key[i]= (uint8_t) ((xdgt0 * 16) + xdgt1);
+	}
+	port_rss_hash_key_update(res->port_id, hash_key);
+}
+
+cmdline_parse_token_string_t cmd_config_rss_hash_key_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_config =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, config,
+				 "config");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_rss_hash_key, port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_hash_key =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key,
+				 rss_hash_key, "rss-hash-key");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, key, NULL);
+
+cmdline_parse_inst_t cmd_config_rss_hash_key = {
+	.f = cmd_config_rss_hash_key_parsed,
+	.data = NULL,
+	.help_str = "port config X rss-hash-key 80 hexa digits",
+	.tokens = {
+		(void *)&cmd_config_rss_hash_key_port,
+		(void *)&cmd_config_rss_hash_key_config,
+		(void *)&cmd_config_rss_hash_key_port_id,
+		(void *)&cmd_config_rss_hash_key_rss_hash_key,
+		(void *)&cmd_config_rss_hash_key_value,
+		NULL,
+	},
+};
+
 /* *** Configure RSS RETA *** */
 struct cmd_config_rss_reta {
 	cmdline_fixed_string_t port;
@@ -1413,7 +1506,7 @@ cmdline_parse_inst_t cmd_showport_rss_hash = {
 
 cmdline_parse_inst_t cmd_showport_rss_hash_key = {
 	.f = cmd_showport_rss_hash_parsed,
-	.data = "show_rss_key",
+	.data = (void *)1,
 	.help_str = "show port X rss-hash key (X = port number)\n",
 	.tokens = {
 		(void *)&cmd_showport_rss_hash_show,
@@ -5322,6 +5415,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(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_config_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 1e332a9..d331eec 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -746,6 +746,34 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
 	printf("\n");
 }
 
+void
+port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key)
+{
+	struct rte_eth_rss_conf rss_conf;
+	int diag;
+
+	rss_conf.rss_key = NULL;
+	diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
+	if (diag == 0) {
+		rss_conf.rss_key = hash_key;
+		diag = rte_eth_dev_rss_hash_conf_update(port_id, &rss_conf);
+	}
+	if (diag == 0)
+		return;
+
+	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;
+	}
+}
+
 /*
  * Setup forwarding configuration for each logical core.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index b9d47c4..66c7736 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -524,6 +524,7 @@ 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);
+void port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key);
 
 /*
  * Work-around of a compilation error with ICC on invocations of the
-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key
  2014-04-30 13:55 ` [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key Ivan Boule
@ 2014-05-01 23:21   ` Ananyev, Konstantin
  2014-05-14  8:43     ` Ivan Boule
  0 siblings, 1 reply; 9+ messages in thread
From: Ananyev, Konstantin @ 2014-05-01 23:21 UTC (permalink / raw)
  To: Ivan Boule, dev

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@dpdk.org] On Behalf Of Ivan Boule
Sent: Wednesday, April 30, 2014 2:55 PM
To: dev@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@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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key
  2014-05-01 23:21   ` Ananyev, Konstantin
@ 2014-05-14  8:43     ` Ivan Boule
  2014-05-14 12:56       ` Ananyev, Konstantin
  0 siblings, 1 reply; 9+ messages in thread
From: Ivan Boule @ 2014-05-14  8:43 UTC (permalink / raw)
  To: Ananyev, Konstantin, dev

Hi Konstantin,

I apologize for my late answer.
I had also read the Niantic documentation that stated to RSS should not 
be enabled/disabled on the fly.
In fact, RSS configuration patches are intended to enable the dynamic 
changement of the RSS configuration of a port (RETA, hash key, hash 
flags), rather than to only disable/enable RSS.
In my opinion, initializing a port with multiple RX queues and RSS 
disableddoes not make sense, and thus there is not reason for allowing 
RSS to be then dynamically enabled in such a case.
For the same reason, once having initialized a port with multiple RX 
queuesand RSS enabled, it does not make sense to then disable RSS on 
that port.

Conversely, creating a single RX queue on a port with RSS enabled does 
makesense to provide packet RSS hash values to the DPDK network stack, 
but, again,it does not make sense to then disable RSS on that port.

According to these considerations, I propose to update the dynamic RSS 
configuration with tests that prevent disabling RSS once initially 
enabled, or enabling RSS once initially disabled.

Regards,
Ivan

On 05/02/2014 01:21 AM, Ananyev, Konstantin wrote:
> 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@dpdk.org] On Behalf Of Ivan Boule
> Sent: Wednesday, April 30, 2014 2:55 PM
> To: dev@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@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


-- 
Ivan Boule
6WIND Development Engineer

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key
  2014-05-14  8:43     ` Ivan Boule
@ 2014-05-14 12:56       ` Ananyev, Konstantin
  0 siblings, 0 replies; 9+ messages in thread
From: Ananyev, Konstantin @ 2014-05-14 12:56 UTC (permalink / raw)
  To: Ivan Boule, dev

Hi Ivan,

Then may be instead of rss_hash_conf_update() introduce just rss_hash_update() that will update only hash key and flags dynamically?
In a same manner we have dev_rss_update/dev_rss_query today?
BTW, I never tried myself to update RSSK and/or MRQE.RSS_Field_Enable on the fly.
Though it is not forbidden explicitly, so I suppose it is ok to do that :)
Thanks
Konstantin    

-----Original Message-----
From: Ivan Boule [mailto:ivan.boule@6wind.com] 
Sent: Wednesday, May 14, 2014 9:44 AM
To: Ananyev, Konstantin; dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key

Hi Konstantin,

I apologize for my late answer.
I had also read the Niantic documentation that stated to RSS should not 
be enabled/disabled on the fly.
In fact, RSS configuration patches are intended to enable the dynamic 
changement of the RSS configuration of a port (RETA, hash key, hash 
flags), rather than to only disable/enable RSS.
In my opinion, initializing a port with multiple RX queues and RSS 
disableddoes not make sense, and thus there is not reason for allowing 
RSS to be then dynamically enabled in such a case.
For the same reason, once having initialized a port with multiple RX 
queuesand RSS enabled, it does not make sense to then disable RSS on 
that port.

Conversely, creating a single RX queue on a port with RSS enabled does 
makesense to provide packet RSS hash values to the DPDK network stack, 
but, again,it does not make sense to then disable RSS on that port.

According to these considerations, I propose to update the dynamic RSS 
configuration with tests that prevent disabling RSS once initially 
enabled, or enabling RSS once initially disabled.

Regards,
Ivan

On 05/02/2014 01:21 AM, Ananyev, Konstantin wrote:
> 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@dpdk.org] On Behalf Of Ivan Boule
> Sent: Wednesday, April 30, 2014 2:55 PM
> To: dev@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@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


-- 
Ivan Boule
6WIND Development Engineer

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-05-14 12:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-30 13:55 [dpdk-dev] [PATCH 0/5] allow to dynamically change RSS configuration Ivan Boule
2014-04-30 13:55 ` [dpdk-dev] [PATCH 1/5] ethdev: check RX queue indices in RETA config against number of queues Ivan Boule
2014-04-30 13:55 ` [dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key Ivan Boule
2014-05-01 23:21   ` Ananyev, Konstantin
2014-05-14  8:43     ` Ivan Boule
2014-05-14 12:56       ` Ananyev, Konstantin
2014-04-30 13:55 ` [dpdk-dev] [PATCH 3/5] app/testpmd: configure RSS without restart Ivan Boule
2014-04-30 13:55 ` [dpdk-dev] [PATCH 4/5] ethdev: allow to get RSS hash functions and key Ivan Boule
2014-04-30 13:55 ` [dpdk-dev] [PATCH 5/5] app/testpmd: allow to configure RSS hash key Ivan Boule

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).