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

Ivan Boule ivan.boule at 6wind.com
Wed May 14 10:43:46 CEST 2014


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


-- 
Ivan Boule
6WIND Development Engineer



More information about the dev mailing list