[dpdk-dev] [PATCH 2/5] ethdev: allow to set RSS hash computation flags and/or key
Ivan Boule
ivan.boule at 6wind.com
Wed Apr 30 15:55:23 CEST 2014
1) Add a new function "rss_hash_conf_update" in the PMD API to dynamically
update the RSS flags and/or the RSS key used by a NIC to compute the RSS
hash of input packets.
The new function uses the existing data structure "rte_eth_rss_conf" for
the argument that contains the new hash flags and/or the new hash key to
use.
2) Add the ixgbe-specific function "ixgbe_dev_rss_hash_conf_update" and the
igb-specific function "eth_igb_rss_hash_conf_update" to update the RSS
hash configuration of ixgbe and igb controllers respectively.
Note:
Configuring the RSS hash flags and the RSS key used by a NIC consists in
updating appropriate PCI registers of the NIC.
These operations have been manually tested with the interactive commands
"write reg" and "write regbit" of the testpmd application.
Signed-off-by: Ivan Boule <ivan.boule at 6wind.com>
---
lib/librte_ether/rte_ethdev.c | 23 +++++++++
lib/librte_ether/rte_ethdev.h | 25 ++++++++++
lib/librte_pmd_e1000/e1000_ethdev.h | 3 ++
lib/librte_pmd_e1000/igb_ethdev.c | 1 +
lib/librte_pmd_e1000/igb_rxtx.c | 93 +++++++++++++++++++++--------------
lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 1 +
lib/librte_pmd_ixgbe/ixgbe_ethdev.h | 3 ++
lib/librte_pmd_ixgbe/ixgbe_rxtx.c | 90 ++++++++++++++++++++-------------
8 files changed, 169 insertions(+), 70 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 473c98b..c00dff0 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1572,6 +1572,29 @@ rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta *reta_conf)
}
int
+rte_eth_dev_rss_hash_conf_update(uint8_t port_id,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct rte_eth_dev *dev;
+ uint16_t rss_hash_protos;
+
+ if (port_id >= nb_ports) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return (-ENODEV);
+ }
+ rss_hash_protos = rss_conf->rss_hf;
+ if ((rss_hash_protos != 0) &&
+ ((rss_hash_protos & ETH_RSS_PROTO_MASK) == 0)) {
+ PMD_DEBUG_TRACE("Invalid rss_hash_protos=0x%x\n",
+ rss_hash_protos);
+ return (-EINVAL);
+ }
+ dev = &rte_eth_devices[port_id];
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_conf_update, -ENOTSUP);
+ return (*dev->dev_ops->rss_hash_conf_update)(dev, rss_conf);
+}
+
+int
rte_eth_led_on(uint8_t port_id)
{
struct rte_eth_dev *dev;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index dea7471..a970761 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -331,6 +331,8 @@ struct rte_eth_rss_conf {
#define ETH_RSS_IPV4_UDP 0x0040 /**< IPv4/UDP packet. */
#define ETH_RSS_IPV6_UDP 0x0080 /**< IPv6/UDP packet. */
#define ETH_RSS_IPV6_UDP_EX 0x0100 /**< IPv6/UDP with extension headers. */
+
+#define ETH_RSS_PROTO_MASK 0x01FF /**< Mask of valid RSS hash protocols */
/* Definitions used for redirection table entry size */
#define ETH_RSS_RETA_NUM_ENTRIES 128
#define ETH_RSS_RETA_MAX_QUEUE 16
@@ -966,6 +968,10 @@ typedef int (*reta_query_t)(struct rte_eth_dev *dev,
struct rte_eth_rss_reta *reta_conf);
/**< @internal Query RSS redirection table on an Ethernet device */
+typedef int (*rss_hash_conf_update_t)(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+/**< @internal Update RSS hash configuration of an Ethernet device */
+
typedef int (*eth_dev_led_on_t)(struct rte_eth_dev *dev);
/**< @internal Turn on SW controllable LED on an Ethernet device */
@@ -1153,6 +1159,8 @@ struct eth_dev_ops {
bypass_wd_reset_t bypass_wd_reset;
#endif
+ /** Configure RSS hash protocols. */
+ rss_hash_conf_update_t rss_hash_conf_update;
};
/**
@@ -2859,6 +2867,23 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
*/
int rte_eth_dev_bypass_wd_reset(uint8_t port);
+ /**
+ * Configuration of Receive Side Scaling hash computation of Ethernet device.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param rss_conf
+ * The new configuration to use for RSS hash computation on the port.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if port identifier is invalid.
+ * - (-ENOTSUP) if hardware doesn't support.
+ * - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_rss_hash_conf_update(uint8_t port_id,
+ struct rte_eth_rss_conf *rss_conf);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..e228c53 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -138,6 +138,9 @@ uint16_t eth_igb_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
uint16_t eth_igb_recv_scattered_pkts(void *rxq,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+int eth_igb_rss_hash_conf_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
int eth_igbvf_rx_init(struct rte_eth_dev *dev);
void eth_igbvf_tx_init(struct rte_eth_dev *dev);
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 673b4de..07ae149 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -193,6 +193,7 @@ static struct eth_dev_ops eth_igb_ops = {
.mac_addr_remove = eth_igb_rar_clear,
.reta_update = eth_igb_rss_reta_update,
.reta_query = eth_igb_rss_reta_query,
+ .rss_hash_conf_update = eth_igb_rss_hash_conf_update,
};
/*
diff --git a/lib/librte_pmd_e1000/igb_rxtx.c b/lib/librte_pmd_e1000/igb_rxtx.c
index 1ebe2f5..5499fd8 100644
--- a/lib/librte_pmd_e1000/igb_rxtx.c
+++ b/lib/librte_pmd_e1000/igb_rxtx.c
@@ -1518,54 +1518,36 @@ igb_rss_disable(struct rte_eth_dev *dev)
E1000_WRITE_REG(hw, E1000_MRQC, mrqc);
}
-static void
-igb_rss_configure(struct rte_eth_dev *dev)
+int
+eth_igb_rss_hash_conf_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
{
struct e1000_hw *hw;
- uint8_t *hash_key;
+ uint8_t *hash_key;
uint32_t rss_key;
uint32_t mrqc;
- uint32_t shift;
uint16_t rss_hf;
uint16_t i;
hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
- if (rss_hf == 0) /* Disable RSS. */ {
- igb_rss_disable(dev);
- return;
- }
- hash_key = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
- if (hash_key == NULL)
- hash_key = rss_intel_key; /* Default hash key. */
-
- /* Fill in RSS hash key. */
- for (i = 0; i < 10; i++) {
- rss_key = hash_key[(i * 4)];
- rss_key |= hash_key[(i * 4) + 1] << 8;
- rss_key |= hash_key[(i * 4) + 2] << 16;
- rss_key |= hash_key[(i * 4) + 3] << 24;
- E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), i, rss_key);
+ hash_key = rss_conf->rss_key;
+ if (hash_key != NULL) {
+ /* Fill in RSS hash key */
+ for (i = 0; i < 10; i++) {
+ rss_key = hash_key[(i * 4)];
+ rss_key |= hash_key[(i * 4) + 1] << 8;
+ rss_key |= hash_key[(i * 4) + 2] << 16;
+ rss_key |= hash_key[(i * 4) + 3] << 24;
+ E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), i, rss_key);
+ }
}
-
- /* Fill in redirection table. */
- shift = (hw->mac.type == e1000_82575) ? 6 : 0;
- for (i = 0; i < 128; i++) {
- union e1000_reta {
- uint32_t dword;
- uint8_t bytes[4];
- } reta;
- uint8_t q_idx;
-
- q_idx = (uint8_t) ((dev->data->nb_rx_queues > 1) ?
- i % dev->data->nb_rx_queues : 0);
- reta.bytes[i & 3] = (uint8_t) (q_idx << shift);
- if ((i & 3) == 3)
- E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword);
+ rss_hf = rss_conf->rss_hf;
+ if (rss_hf == 0) { /* Disable RSS */
+ igb_rss_disable(dev);
+ return 0;
}
- /* Set configured hashing functions in MRQC register. */
+ /* Set configured hashing protocols in MRQC register */
mrqc = E1000_MRQC_ENABLE_RSS_4Q; /* RSS enabled. */
if (rss_hf & ETH_RSS_IPV4)
mrqc |= E1000_MRQC_RSS_FIELD_IPV4;
@@ -1586,6 +1568,43 @@ igb_rss_configure(struct rte_eth_dev *dev)
if (rss_hf & ETH_RSS_IPV6_UDP_EX)
mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP_EX;
E1000_WRITE_REG(hw, E1000_MRQC, mrqc);
+ return 0;
+}
+
+static void
+igb_rss_configure(struct rte_eth_dev *dev)
+{
+ struct rte_eth_rss_conf rss_conf;
+ struct e1000_hw *hw;
+ uint32_t shift;
+ uint16_t i;
+
+ hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /* Fill in redirection table. */
+ shift = (hw->mac.type == e1000_82575) ? 6 : 0;
+ for (i = 0; i < 128; i++) {
+ union e1000_reta {
+ uint32_t dword;
+ uint8_t bytes[4];
+ } reta;
+ uint8_t q_idx;
+
+ q_idx = (uint8_t) ((dev->data->nb_rx_queues > 1) ?
+ i % dev->data->nb_rx_queues : 0);
+ reta.bytes[i & 3] = (uint8_t) (q_idx << shift);
+ if ((i & 3) == 3)
+ E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword);
+ }
+
+ /*
+ * Configure the RSS key and the RSS protocols used to compute
+ * the RSS hash of input packets.
+ */
+ rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
+ if (rss_conf.rss_key == NULL)
+ rss_conf.rss_key = rss_intel_key; /* Default hash key */
+ (void) eth_igb_rss_hash_conf_update(dev, &rss_conf);
}
/*
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 6dd52d7..5910501 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -300,6 +300,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
.bypass_ver_show = ixgbe_bypass_ver_show,
.bypass_wd_reset = ixgbe_bypass_wd_reset,
#endif /* RTE_NIC_BYPASS */
+ .rss_hash_conf_update = ixgbe_dev_rss_hash_conf_update,
};
/*
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..3d33ad2 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -235,6 +235,9 @@ uint16_t ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+int ixgbe_dev_rss_hash_conf_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
/*
* Flow director function prototypes
*/
diff --git a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
index 7930dbd..877ecfd 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c
@@ -2291,50 +2291,37 @@ ixgbe_rss_disable(struct rte_eth_dev *dev)
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
-static void
-ixgbe_rss_configure(struct rte_eth_dev *dev)
+int
+ixgbe_dev_rss_hash_conf_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
{
struct ixgbe_hw *hw;
- uint8_t *hash_key;
- uint32_t rss_key;
+ uint8_t *hash_key;
uint32_t mrqc;
- uint32_t reta;
+ uint32_t rss_key;
uint16_t rss_hf;
uint16_t i;
- uint16_t j;
- PMD_INIT_FUNC_TRACE();
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
+ hash_key = rss_conf->rss_key;
+ if (hash_key != NULL) {
+ /* Fill in RSS hash key */
+ for (i = 0; i < 10; i++) {
+ rss_key = hash_key[(i * 4)];
+ rss_key |= hash_key[(i * 4) + 1] << 8;
+ rss_key |= hash_key[(i * 4) + 2] << 16;
+ rss_key |= hash_key[(i * 4) + 3] << 24;
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, rss_key);
+ }
+ }
+ rss_hf = rss_conf->rss_hf;
if (rss_hf == 0) { /* Disable RSS */
ixgbe_rss_disable(dev);
- return;
- }
- hash_key = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key;
- if (hash_key == NULL)
- hash_key = rss_intel_key; /* Default hash key */
-
- /* Fill in RSS hash key */
- for (i = 0; i < 10; i++) {
- rss_key = hash_key[(i * 4)];
- rss_key |= hash_key[(i * 4) + 1] << 8;
- rss_key |= hash_key[(i * 4) + 2] << 16;
- rss_key |= hash_key[(i * 4) + 3] << 24;
- IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, rss_key);
- }
-
- /* Fill in redirection table */
- reta = 0;
- for (i = 0, j = 0; i < 128; i++, j++) {
- if (j == dev->data->nb_rx_queues) j = 0;
- reta = (reta << 8) | j;
- if ((i & 3) == 3)
- IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), rte_bswap32(reta));
+ return 0;
}
- /* Set configured hashing functions in MRQC register */
- mrqc = IXGBE_MRQC_RSSEN; /* RSS enable */
+ /* Set configured hashing protocols in MRQC register */
+ mrqc = IXGBE_MRQC_RSSEN; /* Enable RSS */
if (rss_hf & ETH_RSS_IPV4)
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
if (rss_hf & ETH_RSS_IPV4_TCP)
@@ -2354,6 +2341,43 @@ ixgbe_rss_configure(struct rte_eth_dev *dev)
if (rss_hf & ETH_RSS_IPV6_UDP_EX)
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+ return 0;
+}
+
+static void
+ixgbe_rss_configure(struct rte_eth_dev *dev)
+{
+ struct rte_eth_rss_conf rss_conf;
+ struct ixgbe_hw *hw;
+ uint32_t reta;
+ uint16_t i;
+ uint16_t j;
+
+ PMD_INIT_FUNC_TRACE();
+ hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /*
+ * Fill in redirection table
+ * The byte-swap is needed because NIC registers are in
+ * little-endian order.
+ */
+ reta = 0;
+ for (i = 0, j = 0; i < 128; i++, j++) {
+ if (j == dev->data->nb_rx_queues) j = 0;
+ reta = (reta << 8) | j;
+ if ((i & 3) == 3)
+ IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2),
+ rte_bswap32(reta));
+ }
+
+ /*
+ * Configure the RSS key and the RSS protocols used to compute
+ * the RSS hash of input packets.
+ */
+ rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf;
+ if (rss_conf.rss_key == NULL)
+ rss_conf.rss_key = rss_intel_key; /* Default hash key */
+ (void) ixgbe_dev_rss_hash_conf_update(dev, &rss_conf);
}
#define NUM_VFTA_REGISTERS 128
--
1.7.10.4
More information about the dev
mailing list